Combining a Rails like framework that makes things easy with a language who's idioms prioritize simplicity seems like a great combination.
I think that's what makes Phoenix and Elixir so nice to use. The primitives Phoenix uses aren't too far from the surface, and the default setup is fairly batteries included without ruling out future growth.
The best of both worlds, in my opinion, is a loosely coupled set of opinionated tools and libraries, but that also has a tool that provides a unifying interface into the "golden path" for using those together to provide some functionality.
Provides the “easy” for 95% of usecases and an “eject” button that unwraps everything and puts it under you control for the last 5%.
This is almost it. A few more things I think one wants:
- Do most of the coupling and plumbing yourself, IoC is evil when applied to things that do too much.
- Control the application state - see above.
- Be free to substitute any major part, be able to compose them freely.
- Re-use and extracting libraries from past work to be convenient, robust and affect past / maintenance-mode projects positively too.
- Be able to defer extracting libraries and generalizing up to the time you actually need to.
- Decouple code organization from artifact deployment.
- Be absolutely free in how you design and write domain logic and information processing - this is the brain of an application.
- Be absolutely free in how you design and write the UI - this is the body of an application.
- Have the tooling/utilities around code that fit your workflows and business needs.
I've come to the conclusion that full-stack frameworks in the style of Rails/Laravel/Django get in the way of some of the above and don't provide enough to make the above possible by themselves. I think the answer is not "use this framework" or even "build this framework".
It starts with your business/domain needs and builds from there - custom and simple. It builds up slowly and steadily like a garden that reflects your team's personality. It takes a careful, comprehensive, holistic approach. There are angles from version control, to project management to deployment that are all incorporated.
Rails chose idioms and conventions that prioritize speed at the cost of complexity. The “included batteries” are not the problem.
You're paying the tax at some point, but if that's at the start of the project it might be high enough to stop it in its tracks. A mature Rails or Django project require abstracting configuration later on in development which is a different sort of tax.
Convention over configuration absolutely has it's perils. I've unfortunately (fortunately?) hit this enough times with Clojure, I know the ecosystem well-enough I'd personally pick composition for a personal project. In a team project where composition makes collaboration difficult (generally a communication and experience problem) I'd probably choose another language with an opinionated framework.