Dobrze, jesteśmy już płynni w analizie statycznej naszej aplikacji, pisania supervisor i tak sobie poruszania się po mix. Pora więc zacząć zagłębiać się trochę bardziej w to co daje nam mix a co umożliwi nam płynne pisanie aplikacji.

Na samym początku poznaliśmy pierwszy typ aplikacji jakie możemy stworzyć z wykorzystaniem mix – po prostu mix new. Kilka tygodni temu zaś poznaliśmy drugi typ aplikacji tworzonych za pomocą mix new, tym razem z parametrem --sup przy tworzeniu aplikacji z wykorzystaniem mix. Parametr ten stworzył nam szablon z kodem który inicjalizował Supervisor i w którym mogliśmy wstawiać nasze własne worker i supervisor. Nic specjalnego, a jednak trochę mniej do pisania. Z tej opcji będziemy pewnie nie raz korzystać, albo przynajmniej ja będę :)

Dziś poznamy trzecie i ostatni typ aplikacji jakie oferuje nam mix (domyślnie oferuje) mix new z parametrem --umbrella. Użyty ma pierwszeństwo na --sup, i podanie tych dwóch parametrów na raz niweluje --sup. To co robi --umbrella to tworzy nam projekt projektów. W świecie .NET nazywamy taki projekt solution lub jak to w Polsce mówią solucje (i o dziwo to jest ok…). Czyli miejsce, które wie o wszystkich pozostałych projektach, jest wstanie nimi zarządzać, przekazywać zależności jak i gromadzić zależności zewnętrzne (taki nuget packages for solution).

Operacja:

mix new eu --umbrella

Wygeneruje nam dużo mniej plików niż standardowy mix new. Po pierwsze, wygeneruje nam on katalog apps w którym będziemy gromadzić nasze projekty/aplikacje. Po drugie nie wygeneruje on nam testów ani żadnych libów itp. Testy są per aplikacja (patrz zdanie wyżej Po pierwsze) ale można je uruchamiać z poziomu eu. Po trzecie, to co nam zostało wygenerowane różni się zawartością od tego co normalnie mamy.

Czyli operacja stworzenia projektu eu wygeneruje nam output:

* creating .gitignore
* creating README.md
* creating mix.exs
* creating apps
* creating config
* creating config/config.exs

Your umbrella project was created successfully.
Inside your project, you will find an apps/ directory
where you can create and host many apps:

    cd eu
    cd apps
    mix new my_app

Commands like "mix compile" and "mix test" when executed
in the umbrella project root will automatically run
for each application in the apps/ directory.

Co fajne, operacja ta mówi nam dokładnie co możemy zrobić i jak to będzie działało. Prawie to samo co ja napisałem tylko że w jakimiś obcym języku którego nikt nie rozumie ;)

Zanim przejdziemy dalej do opisu co tutaj jest nowego i co możemy zrobić, stwórzmy sobie dwie aplikacje, w tym celu:

cd eu/apps
mix new pingpong --sup
mix new chat

Specjalnie zrobiłem --sup byście zobaczyli czym i czy w ogóle to się różni od tego co robiliśmy przez ostatnie tygodnie, to już zadanie dla was :)

Możemy sprawdzić czy wszystko nam śmiga odpalając z /eu

$ mix compile
==> chat
Compiling 1 file (.ex)
Generated chat app
==> pingpong
Compiling 1 file (.ex)
Generated pingpong app

$ mix test
==> chat
Compiling 1 file (.ex)
Generated chat app
==> pingpong
Compiling 1 file (.ex)
Generated pingpong app
==> chat
.

Finished in 0.03 seconds
1 test, 0 failures

Randomized with seed 960000
==> pingpong
.

Finished in 0.03 seconds
1 test, 0 failures

Randomized with seed 23000

Możemy też skorzystać z iex tak jak zawsze:

$ iex -S mix

Jak nam to wszystko działa, to możemy przejść dalej.

Umbrella różni się tym od innych normalnych projektów (new i new --sup), że nie ma ona żadnej implementacji, nie jest też aplikacją. Jest po prostu bytem grupującym prywatne zależności.

Jeżeli porównamy sobie pliki mix.exs z projektu new --umbrella z projektem który nie jest częścią ubmberlla, to zobaczymy pewne cechy wspólne:

def project do
  [apps_path: "apps", # tutaj jest różnica, ścieżka zamiast app:
    build_embedded: Mix.env == :prod, # tak samo
    start_permanent: Mix.env == :prod, # tak samo
    deps: deps]
end

apps_path mówi, gdzie znajdą się aplikację. Normalnie mamy tutaj app: który określa nazwę projektu/aplikacji. Zresztą polecam otworzyć sobie plik mix.exs z chat na przykład. Zobaczymy tam resztę “brakujących” kluczy ze standardowego projektu, czyli app:, elixir:, version:. Ale także zobaczymy kilka nowych, które robią tylko jedno, określają wspólną lokalizację dla wszystkich projektów: konfiguracji, build, zależności.

Na przykład config.exs w umbrella zbiera wszystkie pozostałe config.exs a aplikacji w folderze apps. Dzięki czemu, wszystkie aplikacje są tak samo skonfigurowane. Przydatne.

Jeżeli chodzi o zależności to jest to tak, że jest jedno miejsce ich ściągania, ale nie definiowana!! To bardzo ważne. To znaczy, że nie możemy stworzyć jednej listy zależności i móc ją wykorzystać w każdej aplikacji. Nie, musimy dla każdej aplikacji stworzyć listę zależności. Jednak o tym jak dokładnie zależności działają to jeszcze napiszę osobny post. Tutaj dla naszej wiedzy na razie, możemy zrobić tak by nasz projekt chat, wymagał pingpong. By to zrobić w chat mix.exs należy podmienić deps/0 na:

defp deps do
  [{:pingong, in_umbrella: true}]
end

To spowoduje, że zanim w ogóle chat wystartuje, :pingpong będzie już odpalony i działał sobie w tle.

I to chyba tyle jeżeli chodzi o projekty typu umbrella. Reszta rozbija się o to czym jest Mix.Project, use Application i deps. Ale o tym wszystkim sobie opowiemy wtedy kiedy będzie na to pora.

To co jest najważniejsze to, warto zapamiętać, że w elixir też mamy byt grupujący projekty/aplikacje – w .NET jest to solution. Tutaj zwie się to umbrella i mix oraz iex są na tyle inteligentni, że wiedzą, iż działają w kontekście umbrella czy też nie.

Kiedy warto skorzystać z umbrella? To pytanie pozostawię bez odpowiedzi do póki nie poznamy deps. Wtedy się wyklaruje co i jak, lub powinno. Jak na razie ja osobiście nie miałem potrzeby w ogóle korzystać z mix new :) a co dopiero z mix new --umbrella czy też mix new --sup. Wszystko robiłem w iex. Teraz to się pewnie zmieni więc będę też w stanie wam z boju powiedzieć co i jak :)

PS. Stosuje zamiennie Projekt i Aplikacja. Bo to tutaj w kontekstach w których to używałem było jednym i tym samym.

1 KOMENTARZ

Comments are closed.