Use generic names for Phoenix app and web folders

I’m assuming I’m missing something so can anybody tell me why I should use generic names for the app and web folder for a phoenix application.

E.g., instead of lib/demo and lib/demo_web use lib/app and lib/web. Instead of Demo and DemoWeb use App and Web module namespaces.

I get you would want the OTP application name to be specific but I’ve tried this change out on a small project and it feels good.

If you ever merge two projects that use that scheme, say in an umbrella, you’re going to be in for some pain 3:-). This is not going to be an issue for 85.36% of people (but I’m already in a project where I cannot do that; my umbrella has an phoenix-based admin panel for some “headless” deployments with no customer facing web, and a separate Phoenix based customer facing web app.

1 Like

I kind of am in the generic camp as well, but with a twist. We run multiple projects as an agency and it makes somewhat switching between these projects easier. What I think about “generic” names are not the same @gshaw does, however. My usual set up is that we start with umbrella project containing:

  • apps/db - ecto schemas go there, no or very little business logic
  • apps/core - the “services” layer if you want, workflows that handle business logic
  • apps/ui - the Phoenix user interface. This does not further have ui_web as it’s not necessary, everything in UI is “web” so no need for extra namespacing
  • [maybe] apps/admin - another Phoenix interface, or maybe just namespace where things like exq admin panel, LiveDashboard etc. are mounted and exposed under different port / host than UI
  • [maybe] apps/api - Phoenix/Absinthe endpoint if UI needs API or app has separate API it exposes

And these apps have “generic” lib folders such as “apps/db/lib/db” and “apps/core/lib/core” etc. There is no space for app name, i.e. demo anywhere, usually.

I don’t think merging two projects happens often enough to justify PrefixingEverythingWithYourProjectName. and having a ‘top-level namespace’ for all modules is just adding to the typing and reduces developer experience. When you have to rename things, the sed and/or IDE that can help with refactoring comes in handy.

With my scheme, whenever I am stepping in the project I can assume there will be DB.Repo, DB.User/Account and UI.Endpoint, and something like Core.Registration or similar. Makes life just a bit easier to standardize.

4 Likes

I think it’s fantastic that Phoenix is agnostic about these things; you have a very different workflow than I do since you are deploying for different but similar contracts and you want them to look the same and avoid context switching drag; I have only one system but I need to manage dependencies carefully because I’m deploying self-similar software in the cloud, on prem, and on-prem on customer hardware each which needs to have distinct sets of contents! Of course the framework is not so prescriptive that one of us has to feel like we’re up a creek without a paddle.

It is so good to hear about these patterns though because who knows what I will need in the future!

Out of interest, do you have any blog-posts on how you go about creating such a set-up? Might be useful for the wider Elixir community since this is a bit of a deviation from the standard mix phx.new foo --umbrella output.

When using Boundary I haven’t seen a need for an umbrella project so I don’t use them. I imagine there are use cases but I haven’t found one and they add a lot of complexity. The biggest benefit I see is the separation of concerns but this can be enforced with Boundary.

As to setting up a project to use App and Web, it’s just a matter of doing a global search and replace on the identifiers and file names.

2 Likes