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

Use Cases and building Phoenix applications aro...

Use Cases and building Phoenix applications around them

Using Use Cases in modelling your phoenix application and contexts.

Avatar for Jakub Pięta

Jakub Pięta

June 11, 2019

More Decks by Jakub Pięta

Other Decks in Programming

Transcript

  1. https://www.usability.gov/how-to-and-tools/methods/use-cases.html “A use case is a written description of how

    users will perform tasks on your website. It outlines, from a user’s point of view, a system’s behaviour as it responds to a request. Each use case is represented as a sequence of simple steps, beginning with a user's goal and ending when that goal is fulfilled.”
  2. defmodule Chores.Laundry do def create_laundry do . . . end

    def update_laundry do . . . end . . . end defmodule Chores.Laundryman do # laundryman user specific logic end
  3. Classic approach • Context for Laundryman • basic User stuff

    • Context for Laundry: • create, update and delete • Additional functions to handle our 
 Use Case create_* update_* delete_* sort_* wash_* dry_* fold_*
  4. defmodule Chores.Laundry.DoLaundry do # scrap logic from Phoenix generators end

    defmodule Chores.Laundry do # delegates to use cases modules (optional) end defmodule Chores.Laundryman do # laundryman user specific logic end
  5. defmodule Chores.Laundry.DoLaundry do def call(args) do # handle the use

    case with private functions end defp sort(args) do . . . end defp wash(args) do . . . end defp dry(args) do . . . end defp fold(args) do . . . end end
  6. defmodule Chores.Laundry.DoLaundry do def call(input_data) do with {:ok, laundry} <-

    sort(input_data), {:ok, laundry} <- wash(laundry), {:ok, laundry} <- dry(laundry), {:ok, laundry} <- fold(laundry) do {:ok, laundry} end . . . end
  7. defmodule Chores.Laundry.DoLaundry do defmodule Data do @type t :: %__MODULE__{

    laundryman_id: String.t(), laundry_items: list } @enforce_keys [:laundryman_id, :laundry_items] defstruct [:laundryman_id, :laundry_items] def new(params) do %Data{ laundryman_id: params[:laundryman_id], laundry_items: params[:laundry_items] } end end . . . end
  8. defmodule Chores.Laundry.DoLaundry do . . . def call(params) do data

    = Data.new(params) pipeline(data) end defp pipeline(data) do with {:ok, laundry} <- sort(data), {:ok, laundry} <- wash(laundry), {:ok, laundry} <- dry(laundry), {:ok, laundry} <- fold(laundry) do {:ok, laundry} end . . . end
  9. defmodule Chores.Laundry.DoLaundry do defmodule Data do @type t :: %__MODULE__{

    laundryman_id: String.t(), laundry_items: list } @enforce_keys [:laundryman_id, :laundry_items] defstruct [:laundryman_id, :laundry_items] def new(params) do %Data{ laundryman_id: params[:laundryman_id], laundry_items: params[:laundry_items] } end end . . . end
  10. defmodule Chores.Laundry.DoLaundry do defmodule Data do @type t :: %__MODULE__{

    laundryman_id: String.t(), laundry_items: list } @enforce_keys [:laundryman_id, :laundry_items] defstruct [:laundryman_id, :laundry_items] def new(params) do %Data{ laundryman_id: params[:laundryman_id], laundry_items: params[:laundry_items] } end end . . . end
  11. defmodule Chores.Laundry.DoLaundry do . . . def call(params) do data

    = Data.new(params) pipeline(data) end defp pipeline(laundry) do with {:ok, laundry} <- sort(laundry), {:ok, laundry} <- wash(laundry), {:ok, laundry} <- dry(laundry), {:ok, laundry} <- fold(laundry) do {:ok, laundry} end . . . end
  12. defmodule Chores.Laundry.DoLaundry do . . . def call(params) do data

    = Data.new(params) pipeline(data) end defp pipeline(laundry) do with {:ok, laundry} <- sort(laundry), {:ok, laundry} <- wash(laundry), {:ok, laundry} <- dry(laundry), {:ok, laundry} <- fold(laundry) do {:ok, laundry} end . . . end
  13. defmodule Chores.Laundry.DoLaundry do . . . def call(params) do data

    = Data.new(params) pipeline(data) end defp pipeline(laundry) do with {:ok, laundry} <- sort(laundry), {:ok, laundry} <- wash(laundry), {:ok, laundry} <- dry(laundry), {:ok, laundry} <- some_more_processing(laundry), {:ok, laundry} <- fold(laundry) do {:ok, laundry} end . . . end
  14. defmodule Chores.Laundry.DoLaundry do . . . def call(params) do data

    = Data.new(params) pipeline(data) end defp pipeline(laundry) do with {:ok, laundry} <- sort(laundry), {:ok, laundry} <- wash(laundry), {:ok, laundry} <- dry(laundry), {:ok, laundry} <- some_more_processing(laundry), {:ok, laundry} <- fold(laundry) do {:ok, laundry} end . . . end
  15. defmodule Client.Create.HotelReservation do require XXX use XXX.Pipeline defcall [:conn, :params]

    defmodule Data do @type t :: %__MODULE__{ # enforced booking: XXX.HotelBooking.t(), previous_message_id: String.t(), user: %XXX.User{}, # optional agent: %XXX.Agent{} | nil, card: %XXX.Card{} | nil, companions: [%XXX.Companion{}] | nil, confirmation_message: %XXX.Message{} | nil, confirmation_message_body: XXX.BodyType.t() | nil, decoded_previous_message: XXX.BodyType.t() | nil, previous_message: %XXX.Message{} | nil, request: map | nil, response: map | nil, text_message: %XXX.Message{} | nil, text_message_body: XXX.BodyType.t() | nil, . . .
  16. defmodule Client.Create.HotelReservation do require XXX use XXX.Pipeline defcall [:conn, :params]

    defmodule Data do @type t :: %__MODULE__{ # enforced booking: XXX.HotelBooking.t(), previous_message_id: String.t(), user: %XXX.User{}, # optional agent: %XXX.Agent{} | nil, card: %XXX.Card{} | nil, companions: [%XXX.Companion{}] | nil, confirmation_message: %XXX.Message{} | nil, confirmation_message_body: XXX.BodyType.t() | nil, decoded_previous_message: XXX.BodyType.t() | nil, previous_message: %XXX.Message{} | nil, request: map | nil, response: map | nil, text_message: %XXX.Message{} | nil, text_message_body: XXX.BodyType.t() | nil, . . .
  17. defmodule Client.Create.HotelReservation do require XXX use XXX.Pipeline defcall [:conn, :params]

    defmodule Data do @type t :: %__MODULE__{ # enforced booking: XXX.HotelBooking.t(), previous_message_id: String.t(), user: %XXX.User{}, # optional agent: %XXX.Agent{} | nil, card: %XXX.Card{} | nil, companions: [%XXX.Companion{}] | nil, confirmation_message: %XXX.Message{} | nil, confirmation_message_body: XXX.BodyType.t() | nil, decoded_previous_message: XXX.BodyType.t() | nil, previous_message: %XXX.Message{} | nil, request: map | nil, response: map | nil, text_message: %XXX.Message{} | nil, text_message_body: XXX.BodyType.t() | nil, . . .
  18. defmodule Chores.Laundry.DoLaundry do . . . def call(params) do data

    = Data.new(params) pipeline(data) end defp pipeline(laundry) do with {:ok, laundry} <- sort(laundry), {:ok, laundry} <- wash(laundry), {:ok, laundry} <- dry(laundry), {:ok, laundry} <- some_more_processing(laundry), {:ok, laundry} <- fold(laundry) do {:ok, laundry} end . . . end