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

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
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
pgiesin
This should be a simple problem but I just can’t seem to figure it out. I have a standalone Elixir app that won’t find the database. Dep...
New
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
sacepums
Hey guys. I'm new to elixir and im really stocked about it. But I ran into a bit of problem - I need to convert a date sting, for examp...
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
chewm
Hi guys, nice to meet you to the whole forum, I’m new here, I’m trying to configure visual studio code for elixir, right now the intellis...
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
Exadra37
Sometimes I want to check if the input into a function is not a blank string. My first approach: defmodule Example do def do_stuff(s...
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

Other popular topics Top

sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
977 41022 311
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
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
New
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
New
chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
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
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
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
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