bglusman

bglusman

Question/Idea: Can we compile umbrella apps in same order they're started so that implicit dependencies are impossible without causing warnings?

So I was just chatting with a co-worker about pros and cons of Umbrella apps, and we’ve occasionally had a module that didn’t have tests that had dependency on an app in another umbrella app that wasn’t declared/intentional. But it got me wondering, why can’t we have the compiler start clean from the deepest dependency in the umbrella app, and if using --warnings-as-errors have it warn and error if any module/function is referenced that’s not defined in that app or one of it’s dependencies? Maybe I’m missing something, or maybe there’s already a way to do this? (we didn’t always have warnings-as-errors turned on in our deploy compile, so I suppose I could be remembering from before that?)

Curious for thoughts or ideas.

Most Liked

bmitc

bmitc

I am running into this now. I haven’t been able to figure out how to get rid of the compiler warnings in app 2 when app 2 uses modules from app 1 and app 1 already lists app 2 as a dependency in its mix.exs, which means app 2 cannot list app 1 in its mix.exs as that could cause a dependency cycle. When I run mix compile, app 2 always gets compiled first. Is it done alphabetically?

al2o3cr

al2o3cr

As the doctor said to the patient, “have you considered not doing that?” :slight_smile:

App 1 can’t be compiled first, because it needs to have its dependencies compiled first - including app 2!

What you’ve got is a circular dependency; the way to fix the warning is to remove the cycle.

A general approach that I’ve found useful for these situations is to replace the backwards-link with a runtime reference. In app 1, you’d write code like:

thing_from_app2 = App1.App2Bridge.module().some_function_from_app2(...)

# in app1/app2_bridge.ex
defmodule App1.App2Bridge do
  def module do
    Application.get_env(:app1, :app2_module)
  end
end

# in config/config.exs or similar

config :app1, :app2_module, App2.Whatever

This breaks the cycle, but it has a cost: App 1 can’t give any compiler errors if code from app2_module is misused (called with wrong arity, etc) because it doesn’t see those definitions.

You can mitigate that by defining the desired functions explicitly in App1.App2Bridge, but the compiler can’t help you keep those definitions aligned with the definitions from App2.

You can further mitigate that by making App1.App2Bridge a behavior and implementing it on the App2 side; this is allowed since App2 depends on App1. This could also be handy if you’re an ardent devotee of the “fully isolated unit tests” philosophy, since Mox etc depend on behaviors.

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
Rustixir
Hi everyone, im working on find best language/framework/system for high concurrency, high performance and stable performance after wor...
New
Fl4m3Ph03n1x
Background This question comes mainly from my ignorance. Today is Black Friday, one of my favorite days of the year to buy books. One boo...
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 39297 209
New
rms.mrcs
A couple of days ago I was discussing with a friend about different approaches to write microservices. He said that if he was going to w...
New
RudManusachi
What configs will make sense to put to runtime.exs? – A bit of how I configure apps: I have generic configs in config/config.exs, dev...
New
100phlecs
Are there any downsides, like perf issues, to putting all functional components in CoreComponents as long as you prefix it with the conte...
New
AstonJ
Can you believe the first professionally published Elixir book was published just 8 years ago? Since then I think we’ve seen more books f...
New
pdgonzalez872
If this has been asked here before, please point me to where it was asked as I didn’t find it when I searched the forum. Maybe a mailing ...
New
griffinbyatt
Sobelow Sobelow is a security-focused static analysis tool for the Phoenix framework. For security researchers, it is a useful tool for g...
New

Other popular topics Top

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
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
Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
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
klo
Got a question about when to concat vs. prepending items to list then reversing to achieve appending. So i know lists boil down to [1 | ...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 47930 226
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement