Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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.

Chris Bell

March 03, 2017
Tweet

More Decks by Chris Bell

Other Decks in Technology

Transcript

  1. “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. 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. An umbrella application is a single project that is made

    up of one or more local applications.
  4. $ mix test 
 # we can run this from

    the top level
 # (to run all tests in all apps)
 # or inside one of the apps
  5. $ iex -S mix
 # we can also run this

    from the top
 # level to start all the apps inside
  6. 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. “[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
  8. “[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?
  9. Think about breaking your app into smaller pieces that have

    clear responsibilities and defined boundaries
  10. Ecommerce App • Processes Sales • Ships Orders • Manages

    Customer support requests • Manages product catalog
  11. • 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:
  12. Yes, you can think of them as microservices… Read more:

    http://blog.plataformatec.com.br/ 2015/06/elixir-in-times-of-microservices/
  13. We can introduce a single DB app that manages our

    migrations and has access to our database through an Ecto.Repo
  14. 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
  15. 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
  16. 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!
  17. defmodule Sales.Mixfile do def application do [mod: {Sales, []}, applications:

    [:db]] end 
 defp deps do [{:db, in_umbrella: true}] end
 end
  18. Could also have a Repo per application instead of DB

    as separate app. OTHER OPTIONS ARE AVAILABLE:
  19. 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
  20. Our web layer concerns itself with all things web (parsing

    params, reading headers for auth’d users etc)
  21. We have a dependency flow that only points inwards, meaning

    nothing on the inside knows about something on the outside
  22. “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’
  23. • 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:
  24. Of course, this is just one way of doing things

    and it’s not necessarily the right way™
  25. 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
  26. You don’t have to start out with an Umbrella app

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