kanonk

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.

  1. 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"
  1. Would this be considered good practice for configuring a project like this?

Any insights will be appreciated :slight_smile:

Most Liked

jeremyjh

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

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.

Where Next?

Popular in Questions Top

rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a > b) do {:ok, "a"} end if (a < b) do {:ok, b} end if (a == b) do {:ok, "equa...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New

Other popular topics Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New

We're in Beta

About us Mission Statement