Using Your Umbrella – ElixirDaze

Using Your Umbrella – ElixirDaze

A look at what Applications and Umbrella Applications are in Elixir, as well as a deep dive into an approach for structuring your application as bounded contexts using Umbrella Apps.

9ffad8bbc282b748763697965f27b3c8?s=128

Chris Bell

March 03, 2017
Tweet

Transcript

  1. 6.

    “In Elixir an application is a component implementing some specific

    functionality, that can be started and stopped as a unit, and which can be re-used in other systems.” Elixir Application Documentation
  2. 9.

    defmodule MyApp do
 use Application def start(_, _) do import

    Supervisor.Spec, warn: false
 children = [worker(MyApp.Worker, [])] opts = [strategy: :one_for_one]
 Supervisor.start_link(children, opts) end end
  3. 10.

    An umbrella application is a single project that is made

    up of one or more local applications.
  4. 15.

    $ mix test 
 # we can run this from

    the top level
 # (to run all tests in all apps)
 # or inside one of the apps
  5. 16.

    $ iex -S mix
 # we can also run this

    from the top
 # level to start all the apps inside
  6. 17.

    defmodule WebApp.MixFile do # rest of file omitted 
 defp

    deps do # declaring a dependency on an app under # your umbrella is easy [{:sub_app, in_umbrella: true}] end end
  7. 18.
  8. 22.

    “[Bounded Contexts are] a conceptual boundary where a domain model

    is applicable. It provides Ubiquitous Language that is spoken by the team and expressed in its carefully designed software model” Eric Evans: Domain Driven Design
  9. 23.

    “[Bounded Contexts are] a conceptual boundary where a domain model

    is applicable. It provides Ubiquitous Language that is spoken by the team and expressed in its carefully designed software model” Eric Evans: Domain Driven Design Huh?
  10. 24.

    Think about breaking your app into smaller pieces that have

    clear responsibilities and defined boundaries
  11. 27.

    Ecommerce App • Processes Sales • Ships Orders • Manages

    Customer support requests • Manages product catalog
  12. 29.

    • Be tested in isolation • Be developed in isolation

    • Be deployed independently (if you wish) • Hides its complexity from other applications through a defined public interface Each application can:
  13. 30.

    Yes, you can think of them as microservices… Read more:

    http://blog.plataformatec.com.br/ 2015/06/elixir-in-times-of-microservices/
  14. 33.

    We can introduce a single DB app that manages our

    migrations and has access to our database through an Ecto.Repo
  15. 35.

    defmodule DB.Repo do
 use Ecto.Repo, otp_app: :db
 end defmodule DB.Mixfile

    do
 defp deps do [{:ecto, “~> 2.1”}, {:postgrex, “~> 0.13”}] end
 end
  16. 38.

    defmodule Sales.Customer do
 use Ecto.Schema schema “customers” do
 # Relevant

    sales customer fields
 end
 end defmodule Shipping.Customer do
 use Ecto.Schema schema “customers” do
 # Relevant shipping customer fields
 end
 end
  17. 39.

    defmodule Sales.Customer do
 use Ecto.Schema schema “customers” do
 # Relevant

    sales customer fields
 end
 end defmodule Shipping.Customer do
 use Ecto.Schema schema “customers” do
 # Relevant shipping customer fields
 end
 end But we’re duplicating our schemas!
  18. 44.

    defmodule Sales.Mixfile do def application do [mod: {Sales, []}, applications:

    [:db]] end 
 defp deps do [{:db, in_umbrella: true}] end
 end
  19. 45.

    Could also have a Repo per application instead of DB

    as separate app. OTHER OPTIONS ARE AVAILABLE:
  20. 48.

    defmodule API.V1.CheckoutController do plug :ensure_current_user
 plug :ensure_current_order 
 def create(conn,

    params) do user = get_current_user(conn) order = get_current_order(conn)
 Sales.OrderManager.complete_order(user, order, params)
 |> case do {:ok, order} -> render(conn, data: order) {:error, error} -> render_error(conn, 422, data: error) end end
 end
  21. 49.

    Our web layer concerns itself with all things web (parsing

    params, reading headers for auth’d users etc)
  22. 52.

    We have a dependency flow that only points inwards, meaning

    nothing on the inside knows about something on the outside
  23. 54.

    “Code that is loosely coupled isn’t necessarily easy-to-delete, but it

    is much easier to replace, and much easier to change too.” @tef – ‘Write Code That Is Easy To Delete, Not Easy To Extend’
  24. 55.

    • Clear separation of concerns • Your Phoenix app becomes

    very thin • Your application more clearly signals its features and its intent • Simple, unit testable business logic separate from your UI layer What you end up with:
  25. 56.

    Of course, this is just one way of doing things

    and it’s not necessarily the right way™
  26. 59.

    release :api do set applications: [:api] end
 
 release :backoffice

    do set applications: [:backoffice, :another_app] end
 # distillery makes it easy!
 # read more at
 # https://hexdocs.pm/distillery/umbrella-projects.html
  27. 61.

    You don’t have to start out with an Umbrella app

    on day 1. Refactoring into separate applications is easy. TIP
  28. 64.