Given the diversity of opinion in this thread, I don’t think there will be one right way of organizing code in a web context. Preference and background (django, rails, ddd, etc) will play a role in how people organize their code.
My understanding is that the philosophy of Elixir and Phoenix is to build a small core that can be customized for various scenarios and use cases. While the default code organization of Phoenix is oriented towards how it separates concerns (controllers, views, templates, channels), it’s still possible to transpose it to be domain-oriented. However, there a couple of issues that I found doing this: a) it’s not quite obvious how to do it, and b) the changes required felt more like a work-around rather than a supported, well-documented change.
I still think that a domain-oriented code organization, even in the web part of a project, is more favorable for a lot of users. The main reason is this:
In my experience, making a change usually involves touching multiple related files across the controller and templates of the same domain (and sometimes adding/changing a function in the view). But with Phoenix’s default organization I have to keep multiple folders open in my editor and it’s quite distracting to find the files I need to change, especially when template file names look identical in most cases (index.eex, edit.eex, show.eex, etc). With domain-oriented folders I can expand one folder and make all the changes I need there.
To draw an analogy, imagine I’m also building a CLI for my app, and I’m using a CLI framework that by default organizes code like this:
lib
├── app
│ ├── users
│ │ └── ...
│ └── tasks
│ └── ...
│
└── app_cli
├── commands
│ ├── user_command.ex
│ └── task_command.ex
├── args
│ ├── user
│ │ ├── create.ex
│ │ ├── list.ex
│ │ ├── show.ex
│ │ └── update.ex
│ └── task
│ ├── create.ex
│ ├── list.ex
│ ├── show.ex
│ └── update.ex
└── formatters
├── user_formatter.ex
└── task_formatter.ex
This is of course hypothetical, but it’s not far-fetched. Even though the CLI framework knows where to find things in a more predictable way, it made my life harder by making me spend more effort when I need to change the command/args/formatter in a single domain. I’d organize the CLI code like this instead:
lib
├── app
│ ├── users
│ │ └── ...
│ └── tasks
│ └── ...
│
└── app_cli
├── users
│ ├── user_command.ex
│ ├── user_formatter.ex
│ └── args
│ ├── create.ex
│ ├── list.ex
│ ├── show.ex
│ └── update.ex
└── tasks
├── task_command.ex
├── task_formatter.ex
└── args
├── create.ex
├── list.ex
├── show.ex
└── update.ex
Again, that’s just how I’d organize my code. I can expand one folder and focus on it when I’m making changes. Other domains can remain collapsed, keeping distraction low.