Organise files under *controllers* folder similar to *live* and context folder

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. :slight_smile:

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. :slight_smile:

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. :slight_smile: It seems people are fine with the top level live/controllers/templates, but that’s it.

1 Like