Fl4m3Ph03n1x

Fl4m3Ph03n1x

How do you manage umbrella apps with inner dependencies?

Background

I have an umbrella application that has several apps inside. These apps communicate and depend on each other.

So, when I am testing, because I am using mocks, I need to mock their interfaces. Now if you know about mocks or if you have read Jose Valim’s opinion on them (Mocks and explicit contracts « Plataformatec Blog) you know this brings an issue:

  • Using Mocks means I can deviate from the real implementation.

App Structure

Imagine I have an umbrella project with 2 apps:

  • cli (a command line interface)
  • manager (where all the logic is)

Umbrella Project structure

.
├── README.md
├── apps
│   ├── cli
│   └── manager
├── config
│   └── config.exs
├── mix.exs
└── mix.lock

Now, every time I change the manager’s Public API, I have to update the interface on cli, otherwise my tests in cli will pass even though nothing will then work:

cli app stucture

.
├── README.md
├── lib
│   ├── cli.ex
│   └── manager.ex # interface for the manager umbrella app
├── mix.exs
└── test
    ├── cli_test.exs
    ├── support
    └── test_helper.exs

Problems

So, following this pattern, I have a few issues:

  • every time create a new @type in the manager, I have to update all the interfaces that use it, so the projects using manager as a dependency can have access to the new types I created.
  • every time I change manager’s public API, I have to update the projects that use it as a dependency
  • I have a manager.ex file in my cli app, that is just an interface for the manager app. This is confusing, as people reading my code will not intuitively understand this is just an interface so i can create a mock that obeys it (mocks as nouns :D)

Possible solutions?

Given these issues I have considered the following option:

  • create a new app, called interfaces, where I define the interfaces of all umbrella apps.

This would have the following benefits:

  • Changes to the Public API of any app would always be reflected there.
  • All dialyzer @types would be there as well
  • Any project using the Interface app as a dependency would have immediate access to the most updated interfaces and type specs.
  • I would get rid of the manager.ex file because I would import it from the interface app

It would however have the following drawbacks:

  • Any umbrella app would be forced to have 2 dependencies: the interface app, and the app they want to use (in this case, cli would have to import both interface and manager)
  • They would have access to all interfaces and type specs, even if not needed
  • I would still have to change things in two places: the interface app, and the app that implements the interface.

So I am not really sure on how to deal with this issue.

How do you guys deal with this?

Most Liked

LostKobrakai

LostKobrakai

Yeah, but :cli doesn’t need to be able to interact with multiple backends I imagine. :manager is the only one it interacts with. So no decouling in that direction.

So what? To me this is not a problem in itself. If there’s something in manager, which makes testing hard, this might change. But for that fact of the part making it hard, not because I want to not have end to end tests.

egze

egze

I guess. Never thought of it in terms of patterns.

I took this approach from this blog post https://medium.com/onfido-tech/the-not-so-magic-tricks-of-testing-in-elixir-2-2-acdd0368572b
See part about “Don’t mock what you don’t own”. In the context of app, we don’t own api_client, so we make a wrapper for it.

LostKobrakai

LostKobrakai

I guess we already had this conversation, but I personally would not mock internal dependencies in the first place. But manager.ex is one file in :cli, which belongs to :cli and is built to its needs. What exactly would you be copying from :manager and why?

Where Next?

Popular in Discussions Top

matthias_toepp
I’d love to hear what people think about Wisp, the new Gleam web framework started by Gleam’s primary creator Louis Pilfold. Gleam, alon...
New
Jayshua
I recently came across the javascript library htmx. It reminded me a lot of liveview so I thought the community here might be interested....
New
sashaafm
I’m trying to evaluate the best combo/stack for a BEAM Web app. Right now I’m exploring Yaws a bit, after having dealt with Phoenix for a...
New
Fl4m3Ph03n1x
Background A few days ago I was listening to The future of Elixir from Elixir Talks, with Dave Thomas (@pragdave ) and Brian Mitchell. I...
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
pillaiindu
In django there is a cache framework backed by memcached. Rails also puts a lot of emphasis on caching, and even the idea of russian-doll...
New
lucaong
Hello Elixir and Nerves community, I have been working for a while on an open-source embedded key-value database for Elixir, that I call...
230 13924 124
New
New
eteeselink
Hi all, In the last days, two things happened: A blog post titled “They might never tell you it’s broken” made the rounds. It’s about ...
New
Owens
Hello all, I am developing a new mobile app with Flutter frontend and Phoenix backend. The mobile app has real-time task management and c...
New

Other popular topics Top

malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
josevalim
Hi everyone, One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
AstonJ
Please see the new poll here: Which code editor or IDE do you use? (Poll) (2022 Edition) It’s been a while since we first asked this, I...
208 31142 143
New
Qqwy
Update: How to use the Blogs & Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3271 126479 1222
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" => #BSON.ObjectId<58eb1a7a9ad169198c3dXXXX>, "email" => ...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

Latest on Elixir Forum

We're in Beta

About us Mission Statement