paulanthonywilson

paulanthonywilson

What’s wrong with Umbrella Apps?

I like Umbrella projects and pretty much always use them for personal Elixir stuff, especially Nerves things.

But I don’t think this is a popular choice. I’ve never really understood why they are disliked. The two arguments I’ve read against them don’t check out for me: you can’t control the order of config loading (yes you can) and they are for deploying things separately (no they’re not).

Admittedly I have never worked on a huge Umbrella project; The massive monoliths I’ve worked on have all had flat architectures.

What issues have people had that has put them off Umbrella Projects?

Most Liked

sasajuric

sasajuric

Author of Elixir In Action

A few months ago I started consulting on an umbrella project (about 10 apps). The first thing I did was deumbrellization of the project, which brought some benefits:

  • about 2k LOC less, due to removal of the repetitive boilerplate across subprojects
  • faster test and build times
  • simplified folder structure
  • better tooling support for simple projects

As an example of the last point, various paths that are printed by mix tasks (e.g. test IIRC) aren’t “clickable” in vscode (I couldn’t click to open the file in the editor), because the printed paths are missing the apps/myapp/ prefix. I found this extremely annoying and disruptive. This alone is for me the reason to avoid umbrella as much as possible.

Generally, my sentiment is that if the subapps are not deployed separately, the umbrella app doesn’t bring anything useful to the table, compared to single project + boundary. Even if boundary is not used, I find the benefits of umbrella don’t justify the issues mentioned above.

pdgonzalez872

pdgonzalez872

I’ll let more experienced folks chime in regarding the technical reasons.

My personal experience from working in a few large umbrella projects (note that this is not due to the tech itself, just what happened with the folks using it) have mostly shown issues with premature and incorrect separation of concerns. This is a human problem, not a tech one. Symptoms of these are having sub-apps called core, core_db, utils… that are required everywhere in a project. Basically, instead of thinking in contexts within a non-umbrella app, folks try (incorrectly) to abstract those into apps. Sometimes, they mean well too.

If you can’t run tests in your sub-app without requiring other apps, you should likely have a flat structure and use contexts instead. If you have issues with dependencies (your own), you should reconsider the structure as well. Folks can use behaviours and define boundaries within the contexts if they are inclined (and get Mox for free out of the box if done properly). If you share the same database and have multiple sub-apps calling into it (and having issues with it), maybe your abstraction is incorrect. It is self imposed complexity most of the time. Some folks just want to do it too, because, they can.

These have been the bad experiences with it. Again, this is not related to the umbrella structure itself, but they did happen with folks that used it because they could.

This reminds me of the hippo story from “Along came Polly”. If you are a hippo, be a hippo. If you are a flat app, it’s ok! :heart: Along came Polly - hippo story - YouTube

19
Post #2
ityonemo

ityonemo

I think by and large the problem is similar to “don’t use GenServers for code organization”. Likewise, often times people use umbrellas to organize their code, when umbrellas are best used when you have deployment heterogeneity (I think).

They are bad for organization because:

  • they create an extra layer of indirection in your file paths (apps/ directory)
  • it’s easy to wind up with intra-app dependencies that you lose track of.
  • grokking the mix.exs paths is tricky
  • some libraries don’t support umbrellas

A better solution is to just be unafraid to make top level namespaces in the main app (like how Phoenix creates MyApp and MyAppWeb). For example, I often have a Type module that contains project-specific Typing, and a Tools module, and a Db module.

11
Post #3
Nicd

Nicd

I have this non-umbrella app with two Phoenix endpoints, “api” and “web”: lib · trunk · Mikko Ahlroth / minisome · GitLab – And it really wasn’t any hassle at all. They’re both completely separate, yet in the same project. Now only one of them has frontend stuff, so setting up esbuild/webpack for two endpoints would have to be a custom job, but the Elixir side was easy to have separately.

paulanthonywilson

paulanthonywilson

Hi all,

Thanks again for this discussion. I thought it might be worth writing up my conclusions (which may not be the same as your conclusions).

Where Next?

Popular in Discussions Top

fklement
This is a thread to gather some information about the efforts of using elixir in combination with cars or vehicular systems in general. ...
New
heathen
Quite interesting article Google brought me. Didn’t find any mentions about it here. What do you think in general? Would you use togethe...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
bglusman
I’m curious how others in the community deal with first class enums… especially crossing boundaries like database, code logic, and absin...
New
Sergiusz
Hello everyone, I don’t know if my post is appropriate. If it isn’t, you can delete it. After a year of designing and defining the requ...
New
derpycoder
So, anyone got a chance to look at this?!? I’m kind of glad this came along. We can just throw this into our Auth pages and won’t have t...
New
dogweather
I’ve been brainstorming about ways to solve the N-dimensional code organization problem, and am thinking about developing a Smalltalk-lik...
New
New
puemos
I’m working on a platform that allows users to add apps and use them in a writing assistant browser extension (https://anycursor.com). C...
New
ScriptyScott
Hey Folks, I just spent the last couple of days doing a deep dive into using Swoosh with Amazon’s simple email service, check out this t...
New

Other popular topics Top

vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1140 51847 244
New
srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call th...
New
yawaramin
In the Dialyzer docs ( http://erlang.org/doc/man/dialyzer.html#requesting-or-suppressing-warnings-in-source-files ), there is a way to tu...
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
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? https://hexdocs.pm/ecto/Ecto.Repo.h...
New
beno
I will often find my self writing things similar to: case some_value do nil -> something() "" -> something() _ -> someth...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
Nvim
Elixir appears to be a superior language to Python. I don’t see any advantage of Python over Elixir. Are there any?
New

We're in Beta

About us Mission Statement