Hi folks,
I tried Phoenix 1.7 and it is awesome, but I have small suggestion, which in my opinion will organize files in a better way.
So when I use phx.gen.html
to create a controller and its modal and html counter parts like so:
mix phx.gen.html Academy Student students name email age
This will create:
app
|-- academy/
|-- academy.ex
app_web
├── controllers
│ ├── error_html.ex
│ ├── error_json.ex
│ ├── page_controller.ex
│ ├── page_html/
│ ├── page_html.ex
│ ├── student_controller.ex
│ ├── student_html/
│ └── student_html.ex
Then I used again phx.gen.html
to create one more controller and its modal and html
mix phx.gen.html Academy Teacher teachers name email subject
So now this will add to controllers folder some other files
app_web
├── controllers
│ ├── error_html.ex
│ ├── error_json.ex
│ ├── page_controller.ex
│ ├── page_html/
│ ├── page_html.ex
│ ├── student_controller.ex
│ ├── student_html/
│ ├── student_html.ex
│ ├── teacher_controller.ex
│ ├── teacher_html/
│ └── teacher_html.ex
Now you see where are going, suppose this will be large app, and has 50 controllers, we will find in this folders a lot of files and folder and will be confusing specially if we will create _json.ex
part!
My suggestion is, why this couldn’t be like in app
folder or live
folder? I mean each controller in its own folder, containing all related files and folder together, to match with live
at least like so:
app_web
├── controllers
│ ├── error_html.ex
│ ├── error_json.ex
│ ├── page
│ │ ├── page_controller.ex
│ │ ├── page_html
│ │ └── page_html.ex
│ ├── student
│ │ ├── student_controller.ex
│ │ ├── student_html
│ │ └── student_html.ex
│ └── teacher
│ ├── teacher_controller.ex
│ ├── teacher_html
│ └── teacher_html.ex
This will match with live
folder, as every live we create using mix phx.gen.live
usually has its own folder under live
.
I hope I made it clear.
6 Likes
As someone who is not a particularly big fan of colocated files I like this as it’s more “package-y” (which I do like).
I guess the more classic Elixir-y way would be like:
app_web
├── controllers
│ ├── page_controller
│ │ ├── page_html
│ │ └── page_html.ex
│ └── page_controller.ex
For what it’s worth—since this is something that generally gets to me especially since it feels like there is a bit of a push towards it—I really dislike this manner of colocation because I only ever use tree browsers to get a sense of the structure. When I see the flat colocation structure, it’s incredibly noisy (which I believe is what you’re getting).
This is because if I think of an application general tree structure (talking module tree, not file tree), controllers are an entry point then drill down into their views. I think we’re past the world of “shared views” because we now have components so there is no reason to want to see a giant list of views.
To go further down the bike sheddy rabbit hole, I really like the “classic” pattern of foo.ex
colocated with a foo/
directory. I’ve worked with people and seen recent projects that don’t do this, and I understand the distaste (digging into Rust lately I’ve seen cargo programmatically allows both styles) but when it comes to glancing a file tree, it’s really nice seen bare files as entry points and then if there are supporting files, I know that because there is a related directory. And then if I see a directory with no bare .ex
file, well, I don’t know what that is off the bat but I know it’s something to be considered different.
Anyway, that last paragraph was super bike-sheddy but I just appreciate your post.
1 Like
Ya, I do also like what you proposed, Elixir-y way.
1 Like
Your approach is fine and I might personally even prefer it, and Phoenix will allow you to do both. But speaking from experience, whenever the module structure did not reflect the file structure in Phoenix, people would strongly dislike that too. So some people would expect your code to define Page.PageController
, Page.PageHTML
and so on, which is of course too verbose. And defining only Page.Controller
leads to other sorts of ambiguity (imagine trying to a find a given Controller
alias).
In other words, you can/should go for it. But I suspect if we had gone with it, we would have folks asking to change it to the current one. YMMV.
7 Likes
But speaking from experience, whenever the module structure did not reflect the file structure in Phoenix
Yes, that’s true, but this is not always the case, for example when we use
mix phx.gen.live Staff Teacher teachers name email subject
a live
folder will be created, underneath it one more folder named teacher_live/
, but the live
folder itself in not part of the module FQDM (i.e AppWeb.TeacherLive
and not AppWeb.Live.TeacherLive
) and we are fine with that, because we expect any module name has *Live
, will be under live
folder. The same applies when creating controllers or views in older versions of phoenix, you don’t see views
or controllers
as part of module name for any file underneath these two folders.
What I say, with this new structure of controllers
folder, it will be really noisy folder with flat structure full of controllers and views and templates in the same level, yes I know I can just change that, but would be nice if this was done automatically when using mix phx.gen.html
or other generators.
we would have folks asking to change it to the current one. YMMV.
Yes of course, you will never be able to satisfy everyone’s wish.
1 Like
Yes, that’s the logic we applied when we put contexts inside the context folder (similar to your controller proposal). It didn’t stop the criticism though. It seems people are fine with the top level live/controllers/templates, but that’s it.
1 Like