kanonk
On structuring and configuring a web application project in Elixir
I’m currently developing a web application and am wondering if I’m heading in the right direction.
I decided to opt for Dave Thomas’ approach, where each application resides in its own directory. And all dependencies between them is linked through path. i.e.:
# mix.exs
defp deps do
[
{:accounts, [path: "../accounts"]},
{:mailer, [path: "../mailer"]},
]
end
And the dependencies are as follows
web
├── mailer (../mailer)
└── accounts (../accounts)
└── db (../db)
First thing I’m unsure of, is the separation between accounts and db. As the project grows and I need a new module, i.e. products. This would be a new dependency of web, and would also be dependent on db.
web
├── mailer (../mailer)
└── accounts (../accounts)
└── db (../db)
└── products (../products)
└── db (../db)
One of the reasons I bought into this method of dependencies is that it strives to make a module reusable. In this case accounts and inventory would not be reusable applications on their own.
- Taking into account the previous statement, is this still a good approach to structure the application, or should it be made simpler?
Another issue I encountered was configuring the application. I want to test each module individually. This leads to many applications needing the same configuration.
I opted for configuring each application within its own folder, and importing it in any of the applications depending on it.
Here is an example of that: accounts loading config from db
# /accounts/config/config.exs
use Mix.Config
import_config "../../db/config/config.exs"
And
# /accounts/config/test.exs
use Mix.Config
import_config "../../db/config/test.exs"
- Would this be considered good practice for configuring a project like this?
Any insights will be appreciated ![]()
Most Liked
jeremyjh
Not everyone agrees, but I think having separate OTP applications applies when your storage or deployment lifecycle differs between the different applications. It does not offer any additional abstraction or information hiding beyond what the module system gives you.
Examples: if your mailer would almost make sense as a third-party or open-source library, or as a component that is developed by a different team in your organization.
Talking about different applications needing access to the same relational database schema I think is misguided; I don’t see a benefit to this.
What we do in our application is having multi-levels of context modules. So Account, Product are contexts, they may have sub-contexts that are more specialized but this is just represented as a normal module tree. Communication across contexts should happen at the root level. If you just look at the modules and functions involved, this is pretty much what you end up with in an umbrella project anyway.
Last Post!
dimitarvp
All true. It is mostly related to human perception IMO; if things are separated in “apps”, “bundles”, “module collections”, “class libraries” etc. then us the people think that bundle to be a semantically isolated unit – which is true often enough but many times it isn’t because it’s simply a device to make the life of the code organizer a bit easier.
To reiterate part of my above comments: for most devs I ever met – even the juniors and the interns – it instinctively makes sense not to breach boundaries where you have a small mechanical hurdle before doing so. Thus I try hard in my work to exploit such brain bugs (or hacks or if you will) in order to make people play nicely with my code. Saves time, saves unnecesary discussions, and works most of the time. And when it doesn’t, I can explain why I do things the way I do – in 2 minutes.
In my experience it definitely does draw the said bright line but we come from different backgrounds and societes so that’s surely a factor in it as well.
As for sharing non-code resources, that’s a problem most programming languages still haven’t solved reliably. I’d go radical and make an entirely new OS that has an OS-wide key/value store that can be a file / string / number / whatever and be it read-only 99% of the time (and have additional security attached to it, like who can even view it). I see no reason to maintain configuration or static assets the way we do it right now – deployment with such a new system would be brain-dead easy… But anyway, we can dream.
In Elixir’s case the priv/ directory IMO complicates more things than it solves. But I have no better idea so I am not bad-mouthing it. Often, it’s a good enough mechanism.
Popular in Questions
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
- #api
- #forms
- #metaprogramming
- #security
- #hex









