What is this about?
Newly generated Phoenix (v1.7) applications come with a lib
directory that is split into two subdirectories:
myapp
for application codemyapp_web
for web code (HTTP endpoint, router, controller, views, etc.)
It looks like this:
myapp
├── application.ex
├── mailer.ex
└── repo.ex
myapp_web
├── components
├── controllers
├── endpoint.ex
├── gettext.ex
├── router.ex
└── telemetry.ex
When the application grows and more and more modules are added you might end up with a long list of files in the lib/myapp
directory that looks similar to this:
myapp
├── accounts
├── accounts.ex
├── admin
├── application.ex
├── auth.ex
├── bililng.ex
├── billing
├── cache.ex
├── documents
├── documents.ex
├── ecto_types
├── ev.ex
├── file.ex
├── format.ex
├── icu.ex
├── logger.ex
├── mailer.ex
├── pricing
├── pricing.ex
├── repo.ex
├── startup.ex
└── vault.ex
myapp_web
├── components
├── controllers
├── endpoint.ex
├── live
├── gettext.ex
├── plugs
├── router.ex
└── telemetry.ex
Due to lack of a better place, the lib/myapp
directory now contains a mix of business logic (context) modules and supporting infrastructure code. This makes it harder to find the code you are looking for and it also makes it harder to reason about the application’s purpose.
How to?
Since in Elixir module names do not have to strictly match file names, we can move the infrastructure code to a separate directory without changing any module names. My personal preference is to call this directory lib/myapp_sys
to keep it short.
The lib/myapp
directory then contains only business logic modules.
Here’s the same list of files as before now split into three directories:
myapp
for business logic codemyapp_sys
for supporting infrastructure codemyapp_web
for web code (HTTP endpoint, router, controller, views, etc.)
And it looks like this:
myapp
├── accounts
├── accounts.ex
├── admin
├── auth.ex
├── bililng.ex
├── billing
├── documents
├── documents.ex
├── pricing
└── pricing.ex
myapp_sys
├── application.ex
├── cache.ex
├── ecto_types
├── ev.ex
├── file.ex
├── format.ex
├── icu.ex
├── logger.ex
├── mailer.ex
├── repo.ex
├── startup.ex
└── vault.ex
myapp_web
├── components
├── controllers
├── endpoint.ex
├── live
├── gettext.ex
├── plugs
├── router.ex
└── telemetry.ex