Buttons840

Buttons840

Separate umbrella apps can access each other despite have no defined dependencies?

I created an umbrella project, and created two apps for testing:

defmodule Appa do
  def hello do
    "this is a string in appa!"
  end
end

and in a separate umbrella app:

defmodule Appb do
  def hello do
    IO.puts "I will print from appb"
    IO.puts Appa.hello()
  end
end

When I call hello from Appb (in a shell started with iex -S mix) it prints:

I will print from appb
this is a string in appa!

I haven’t defined any dependencies between the two apps. I was hoping I would have to explicitly define a dependency between the two apps for this code to work.

Perhaps I’m having this issue because my “apps” are not really “applications” in the Erlang sense of the word? I think I’m not using umbrella apps correctly?

If I were using umbrella apps correctly will explicitly defined dependencies be required then? This is something I would appreciate if it’s possible? I’ve seen too many projects where people will call any code from anywhere, and the project ends up being a ball-of-mud, where all parts of the code depend on all other parts, and changing one part usually requires changing all other parts. I believe having a sane structure, and sane dependencies between “modules” to be one of the most important design principles, and I was wondering to what extend umbrella projects can help with this?

Most Liked

kelvinst

kelvinst

It’s pretty well explained the why already. But sometimes you want it to hardly fail if you use code that you shouldn’t.

For example: if the application A depends on application B, it’s a very well known good practice not to have B depending on A.

If these two applications were not on the same umbrella the code would not compile, and one of the advantages of making umbrella projects is the ability to extract any app under it to reuse it out of your umbrella project. That would not be possible if you have circular dependencies there.

So, I went through this problem and what I have done to make sure it never happen again is very simple:

for app in apps/**; do cd $app && mix test; cd ../..; done

This will try to compile and execute the tests for each application individually. This will make sure you don’t use any code that is not included as a dependency on your application.

jwarlander

jwarlander

Unlike Java for example, Elixir doesn’t require you to import / require other modules in order to use them. As long as the module is loaded into the BEAM, it will “just work”. That’s how you use the Elixir standard library, as well as OTP.

Defining dependencies in mix.exs is just a way to get the build tool to download and compile external dependencies, putting the results into the VM’s load path.

When you create an umbrella project, you’re specifically saying you want all of the included apps compiled and loaded together, usually because they’re so tightly coupled at the time (with regards to new feature development etc at least).

So no, you don’t need to declare any dependencies between them… If you want that, maintain them as entirely separate projects, and accept the pain of handling version control etc separately whenever you need to develop a new feature that requires changes in all two, three or five of them :stuck_out_tongue_winking_eye:

wmnnd

wmnnd

You are right, you should not be able to access one child application from another one without explicitly declaring it a dependency.
However, from your umbrella project, you will be able to use all child apps/modules automatically. Did you maybe start your iex session from the main folder instead of the folder of Appb?

hubertlepicki

hubertlepicki

So I think you have similar (wrong) idea about Erlang/Elixir apps that I did have initially. I thought that having multiple apps loaded on a VM involves some sort of separation, i.e. that one app cannot call public functions on modules from other apps, and the only way to communicate is to pass messages between processes/apps.

This is not the case. When an umbrella project is started (from it’s project root), it will load all the applications on the same VM. The modules of the apps are not separated in any way, and from Appa you can call public functions of modules in Appb.

It’s up to programmer to enforce (or not) the separation. What I like to do for my clients’ projects, is that umbrella apps that will be interacted from the outside, specify some sort of public API. There is no good way that I know of, however, that would limit a programmer from calling other public functions, if they are known. It’s up to you :slight_smile:

Buttons840

Buttons840

Yes, I did. I think the “apps” in an umbrella project should probably be bigger and more self contained than what I was originally picturing.

Thanks for the replies. They answered my question and gave me some good insight into how Elixir and umbrella projects work.

Where Next?

Popular in Questions Top

JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
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
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
Werner
Hi, I’m using Ubuntu 18.04 and after updating to OTP-24.0 yesterday i have this warning when I run “mix local.hex”: 14:57:30.512 [warn] ...
New
script
If I have a string “1000 cfu/ml” . I want to remove the characters and / and space . So the string is like this "1000" What is the ...
New
mgjohns61585
Could someone help me? I'm making my first elixir program, number guessing game. I can't figure out how to convert the user's guess from ...
New
qwerescape
Is there a way to get the call stack or stack trace at any point in the code? Not from exceptions, but an expression that returns how the...
New
mathew4509
I have a list say x = ["23gh", "56kh", "97mh"] I would like to pass each element to Val in each iteration. Say, in iteration 1 -------...
New
johnnyicon
Hi all, I've just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I'm trying to use Postg...
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

Other popular topics Top

Tee
can someone please explain to me how Enum.reduce works with maps
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
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: https://hexdocs.pm/ecto/Ecto.Schema.html#module-...
New
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
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set? Thanks.
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
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
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
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

We're in Beta

About us Mission Statement