khaledh
Discussion about domain-orientated folder structures in Phoenix
Continuing the discussion from Domain-oriented web folder structure:
Essentially:
hello_web
├── controllers
│ ├── foo_controller.ex
│ ├── bar_controller.ex
├── templates
│ ├── foo
│ │ ├── index.html.eex
│ │ ├── ...
│ ├── bar
│ │ ├── index.html.eex
│ │ ├── ...
├── views
│ ├── foo_view.ex
│ ├── bar_view.ex
to:
hello_web
├── foo
│ ├── foo_controller.ex
│ ├── foo_view.ex
│ ├── templates
│ │ ├── index.html.eex
│ │ ├── ...
├── bar
│ ├── bar_controller.ex
│ ├── bar_view.ex
│ ├── templates
│ │ ├── index.html.eex
│ │ ├── ...
I hope @chrismccord will consider making this easier in a future release ![]()
Most Liked
sasajuric
I think this is a very good argument!
The question is is it better to have e.g. UserController and TaskController in the same folder, or would it be better to have UserController, UserView, and corresponding templates in the same folder? I currently can’t see much benefits of the former approach, and I can confirm that I’m occasionally annoyed by the current folder structure when working on the web part. I frequently find I need to navigate between separate folders, which is a bit distracting.
In my experience, most often I need to make changes to all the three aspects of a single entity (e.g. a User), so it seems that grouping per entity would work better for the most cases I’ve seen.
Personally, I’ll think about trying out the alternative approach in my next project.
chrismccord
An option to phx.new would provide two ways of doing the exact same thing, which actually could harm newcomers with an unnecessary choice. Our goals with Phoenix defaults have always been sane defaults that are easily customized for those that require it. Wrt to DDD, we treat the the web as the domain. Grouping templates, views, and controllers is file organization, which the proposed alternative is just fine, but not something the Phoenix team views as preferable. But the point is there is nothing special about our defaults, and to achieve your own desires you can use the same options we use to ship our own out-of-the-box behaviour.
chrismccord
I think we actually agree on this point:
Phoenix is indeed only the web interface to your application. The Tasks and UserManagement contexts would live outside of app_web/.
This would be true if we encouraged users to write their application and web code together, such as app/user_management/controller.ex|user_management.ex, but this would directly couple app code and web code together. If we agree the Phoenix is the delivery mechanism to your application, then it absolutely makes sense to group controllers together, because we are only concerned with dispatching web requests into our application, and converting the results into responses.
For example, if we look at the web directory structure of such an app:
app_web
controllers
user_controller.ex
task_controller.ex
api
v1
task_controller.ex
resolvers
task_resolver.ex
It passes the test of screaming its intent, within the context of The Web. We are translating user and tasks requests into responses. Those controllers may hook into entirely decoupled parts of our application. With a glance, I can immediately see what the web layer is responsible for, down to handling user requests, a JSON an API, and servicing graphql clients for tasks. If the app had grouped the directories per user/task, I would need to hunt down what the web story actually looks like.
So for me our defaults encourage better application design exactly because the web side is only focused on being the delivery mechanism. Of course we don’t force this on folks and you are free to structure your directories as you see fit ![]()
Hopefully that gives insight to our dir structure.
Popular in Discussions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #hex









