I have spent a lot of time thinking about bounded contexts, in elixir and other languages. It is often difficult to work out exactly what they will be up front. When start a new project I often have two namespaces. one called www (not web because most services are likely to be available over the web) and one called operations. Projects then evolve often gaining an admin and/or analytics context. After that stage is when the ‘operations’ context starts breaking down into useful services and perhaps vanishing all together.
And the reason Rails has awesome guides is because of all the people who found it, fell it love with it, and made those guides awesome before you came along.
The fact that they need to focus on learning all of those things is exactly why more shouldn’t be added to it, although I doubt that many, if any, people are finding Phoenix currently that are completely unfamiliar with html, css, and javascript. And it’s not really about them struggling with it, it’s about the fact that they simply aren’t going to want to learn that before they learn to do “cool things.” The expectation for proper organization and use of modules is fine for people who have already committed to using Phoenix. Selling new people requires letting them see what they can do with minimal effort.
Still, no one forces you to use them. And when learning new framework yo’re better off without them anyyway, because instead of answering some questions they just raise more.
I think that Phoenix is not aimed at people that want to do just “cool things”. Phoenix and Elixir is rather aimed at people who understand terms like distributed and fault-tolerant. And to know them, and understand value of distributed and fault tolerant software, you really have to do some real world programming. And if you done that, you know you don’t want sot that’s cool, but rather software that is easy to maintain.
I really, really don’t understand why there is a need for phoenix to give up teaching good practices just because some people can’t or don’t wan’t to spend some time (very little actually) to understand where does those practices come from, and why they may be important.
About a year ago, my team started working on a Phoenix app. We all had experience with Erlang, building web servers, and software development in general. None of us had experience with Phoenix, though, so we followed patterns encouraged by the official docs, generators, and other independent blogs. We started with Phoenix 1.1, so there were no context, and there were still models. We moved quickly, and produced a lot of code in the next few months. Unfortunately, that lead us to a quite interleaved code with unclear boundaries and responsibilities. It became increasingly harder to maintain and extend such code. Some six months after we started, we agreed to clean up our controllers, and move other concerns to “service” modules (which I feel resemble the official contexts being introduced with 1.3). To this date, our code is still not completely there.
My takeaways from this experience are:
Framework plays an important role in determining the code organization. Even as experienced devs, we simply stuck to defaults promoted by Phoenix at the time.
It’s much harder to refactor the code post-fact. Having worked on some terrible legacy (and sadly produced some of my own), I strongly feel that your only chance of keeping the control of your code is to pay attention to it from the very start.
Keeping the Phoenix part of the code (controllers, sockets) focused only on HTTP related tasks, basically making it just the interface to the rest of the system is a very good way to structure any production app.
Therefore, there’s no doubt for me that contexts are a very good idea which will push developers in good direction, promoting better code organization patterns. I agree that this will make things slightly more confusing for newcomers, because it’ another idea they have to grasp. However, I think that this is a good trade-off. A bit of approachability is sacrificed to get much better code organization.
I’m somewhat worried about this mantra myself. I have a feeling that for some people it means “Phoenix is not your OTP application”, and that we should always organize our system as umbrella apps. I definitely don’t share that view. For me, the core idea here is that Phoenix is an http/ws interface to your system. You take the input, validate it, and then invoke some other part of your system (i.e. some function from some module in some other namespace), and finally convert the result of that function into desired output (html, json, …). That’s a clear separation of responsibilities, and can lead to much more readable code. And a readable code is a win for everyone, especially for newcomers.
I think the bridge between his comment and yours is that newer developers shouldn’t be the ones getting paid to architect a new environment for a company’s systems. If they are then they more than likely had a choice in deciding what language to use and if they chose Elixir and Phoenix, you would assume it’s because they knew it already and not that their employer let them pick something and then spend a while learning it.
If a more senior developer chose it then your concerns are largely laid to rest and you get the benefits of a more modular environment for future new hires to come into.
I have rarely seen much beyond “I need a website” type work entrusted entirely to new developers. If somebody with an actual development budget did that for a business application, it would be a shock.
About Phoenix is not your application. For me it means Phoenix is not your whole application. Don’t think of your logic being part of Phoenix application, but rather other way round. Phoenix is just a part of your application, call it a frontend, or UI, or whatever. But write your app in such a way, that it can live on it’s own without a phoenix, so that you can add a CLI for it easily or desktop GUI, or another interface for communication, like system bus, or other than HTTP network protocols. Because you newer now if you’ll need that and writing it like this does not cost anything, beside more thinking how to structure your interfaces well.
I think it happens in startups rather a lot, and startups also place the highest priority on a stack being quick and easy to get stuff built, which is one of Phoenix’s selling points.
Where did you get that from? On the frontpage of the framework I read the following:
A productive web framework that
does not compromise speed and maintainability.
The latter part is exactly what the recent 1.3 changes do address – not compromising maintainability for a notion of being “faster”. I’m certainly of the opinion that the new contexts are explained/marketed in a bit to complex fashion, but the general idea of moving business logic out of phoenix controllers is a much needed change.
I see a few issues/arguments that pop up and never get resolved in these Context threads.
Real examples that have 20+ schemas, 20+ endpoints, real use cases and real business requirements. This is probably the number one thing that will help the community with this problem. It is still early, so I’m sure that this will come in time.
Not acknowledging that a large part of web application development is simple crud. The problem is that contexts add ceremony with little value.
Pretending that the mess made with contexts will be a better mess.
Naming stuff is hard and now we have to name three things the Context namespace, the struct, and then add an interface from the context and the web world.
Most of these are just educational issues that would be better solved by publishing lots of code and blog posts
However, there is a very real need for a standard “I didn’t know what to name this thing, it doesn’t really matter, stop trying to make it matter, just tell me where to shove the thing so I can get back to shipping features.” I think that providing a good enough guideline for the community would yield the incremental change that we need to move forward.
The first word is productive, and not holding people’s hands isn’t compromising on maintainability. If people choose to build non-modular code (which they will still do with contexts anyway), that’s on them, not on Phoenix. Phoenix hasn’t compromised a thing by not trying to steer them to the right place. The right way to get people building better apps is through examples, tutorials, and best practices, not by adding a roadblock to them getting stuff done, even if that roadblock is a very minor one.
If you really feel the need to put something in the actual Phoenix code to encourage modularization, implement something like checking their code whenever a generator is used and spitting out a y/n message to the console along the lines of
Your app looks like it might not be following modular coding best practices.
Check out <some link> to learn more about modularizing your app.
Are you sure you wish to continue? Y/n
I am having a really hard time with this argument. So over everything they need to learn, code organization is the one thing we are going to move to the end of the queue?
Elixir never shied away of introducing concepts to developers: functional programming, pattern matching, immutability, etc. Since nobody seems to be questioning the merit of contexts, rather its accessibility, then the obvious answer is to make it as accessible as possible, as we did the concepts above.
The way to make this discussion productive is:
If developers are acting condescending, let them know about it. The fact different people in this thread have different understanding of what “Phoenix is not your application” means, indicates that you were spot on, and that the “meme” needs to be phased out
Developers need to bring cases and evidence of where contexts work and where contexts don’t. When someone says “contexts are terrible, you should remove it”, to me it feels the equivalent of going to the doctor and saying “my leg hurts, you should remove it”. You very likely want the people that lead the open source projects that you use to take informed decisions, so please help us with cases and evidences
In this thread, we have seen some examples of people having positive experiences with contexts and that’s great. But I have found struggles in other threads, such as when to split contexts, how to access data across contexts, what about umbrella applications, etc. Now is the time to collect those struggles and address this in the documentation, guides, books, blog posts, etc. If after a few iterations the concept is still not clear, then it means something more drastic needs to be done, maybe even remove the feature altogether.
So if you or someone you know are struggling with contexts, let’s talk about those cases, rather than jumping to the conclusion that the leg should be removed. Although I disagree with the premise that contexts are terrible for the future of Phoenix, I am always glad to hear about places we can improve.
But those things are all part of the language, rather than how you use the language.
I do agree that more conversation and knowledge sharing is key to all of this. Getting some more of that rolling was my main purpose in this thread, and I’m more than willing to be shown that I’m wrong.
I would argue that a large number of people came to Elixir and Phoenix for perhaps two reasons in particular:
Performance / scalability (which we get thanks to Erlang/BEAM)
A better way of doing things (which we get thanks to ideas and conventions that José, Chris and others are introducing and incorporating into core areas)
I also believe these are some of Elixir’s best selling points.
While there are quite a lot of early adopter ‘newbies’ (all power to them!) currently the language is most attracted to developers with a little more experience… but this is working out really really well, and not only bodes well for the future of Elixir and Phoenix but will ultimately benefit newbies in the long run.
So personally I am all for contexts and other best practices being incorporated or promoted so long as they are clearly explained; whether via books, guides, talks etc - which the community has already said it’s committed to… we just need a little patience
Check Hex source code for an example application that is migrating from 1.2 to 1.3. It is a very interesting example because in some places it is in a mixed state, with logic still in the “models/schemas”, which is what you would expect a real world application to look like. We definitely need more examples though.
My intuition is that crud is actually nicer with contexts than without contexts. That’s because even when crud-ing, the resources are still related, and the context keeps this relationship together. In the scenario you are mindlessly generating stuff, then the only extra input that contexts require is the context name. CRUD still works.
I am confused. Aren’t those two? The context and the struct? Except by the context name, all names are inflected from the struct.
I dunno. It just seems to me like it’s a situation for best practices. Should the code refuse to compile if a function is over X lines or uses nested ifs?
Maybe not compiling it a bit too harsh, but a warning would be nice Still Phoenix do exactly nothing when you don’t use context, it does allow you to not use them. So it’s not comparable.