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

Context-Driven Development: Architecture your code with Phoenix context

Jenny Shih
October 12, 2021

Context-Driven Development: Architecture your code with Phoenix context

Presented at 2021 ElixirConf by Jenny Shih

Note: There are quite a few gifs in the slides. They can be only uploaded as still images so some effects are gone, but that doesn't affect the values this presentation wants to convey.

Jenny Shih

October 12, 2021
Tweet

More Decks by Jenny Shih

Other Decks in Technology

Transcript

  1. @jenny_codes
    Context-Driven Development
    Architect your Code with Phoenix Context

    View Slide

  2. View Slide

  3. View Slide

  4. https://media.giphy.com/media/NWtFdrEXGwZX2/giphy.gif

    View Slide

  5. • Quick onboarding

    View Slide

  6. • Quick onboarding


    • Effective

    View Slide

  7. • Quick onboarding


    • Effective


    • Using Elixir

    View Slide

  8. https://twitter.com/DJTGIF/status/856856284892729345
    Context

    View Slide

  9. What do I do with contexts?

    View Slide

  10. Outline
    • The cunning challenges of contexts


    • The quest, and what did not work


    • Build-your-own architecture


    • Revisit contexts


    • Context-driven development

    View Slide

  11. Outline
    • The cunning challenges of contexts


    • The quest, and what did not work


    • Build-your-own architecture


    • Revisit contexts


    • Context-driven development

    View Slide

  12. View Slide

  13. “Contexts are dedicated modules that


    expose and group related functionality.“

    View Slide

  14. Model
    Controller
    View
    Request Response

    View Slide

  15. Model
    Controller
    View
    /your_app_web
    /your_app

    View Slide

  16. Phoenix MVC structure
    lib
    ├── your_app
    ├── your_app_web
    Model
    Controller
    View
    /your_app_web
    /your_app

    View Slide

  17. Phoenix MVC structure
    lib
    ├── your_app
    ├── your_app_web
    ├── controllers
    ├── endpoint.ex
    ├── router.ex
    ├── templates
    └── views
    Model
    Controller
    View
    /your_app_web
    /your_app

    View Slide

  18. Phoenix MVC structure
    lib
    ├── your_app
    ├── ???
    ├── ???
    └── ???
    ├── your_app_web
    Model
    Controller
    View
    /your_app_web
    /your_app

    View Slide

  19. Phoenix MVC structure
    lib
    ├── your_app
    ├── ???
    ├── ???
    └── ???
    ├── your_app_web
    Model
    Controller
    View
    /your_app_web
    /your_app
    Context

    View Slide

  20. The cunning challenges of contexts

    View Slide

  21. The cunning challenges of contexts
    • Different layers of concerns are mixed together.

    View Slide

  22. View Slide

  23. View Slide

  24. The cunning challenges of contexts

    View Slide

  25. concept


    of


    context
    Ecto
    business
    logic
    juggler by Orin zuu from the Noun Project
    The cunning challenges of contexts

    View Slide

  26. The cunning challenges of contexts
    • Different layers of concerns are mixed together.


    • Relationships between components are ambiguous.

    View Slide

  27. from Phoenix of
    fi
    cial guide
    “Sometimes it may be tricky to determine if two resources
    belong to the same context or not. In those cases, prefer
    distinct contexts per resource and refactor later if necessary. “
    The cunning challenges of contexts

    View Slide

  28. Outline
    • The cunning challenges of contexts


    • The quest, and what did not work


    • Build-your-own architecture


    • Revisit contexts


    • Context-driven development

    View Slide

  29. What to do with context?
    • Look at open-source projects?

    View Slide

  30. What to do with context?
    • Look at open-source projects?


    • Domain Driven Design?

    View Slide

  31. source: https://youtu.be/tMO28ar0lW8

    View Slide

  32. https://gfycat.com/elderlyhatefulhornet
    Challenge accepted.

    View Slide

  33. https://www.domainlanguage.com/wp-content/uploads/2016/05/DDD_Reference_2015-03.pdf

    View Slide

  34. View Slide

  35. https://gfycat.com/composedimportantavians

    View Slide

  36. 💡

    View Slide

  37. https://gph.is/g/4zqknpn?tc=1 via @giphy
    architecture

    View Slide

  38. from Phoenix of
    fi
    cial guide
    “Contexts are dedicated modules that


    expose and group related functionality.“

    View Slide

  39. Outline
    • The cunning challenges of contexts


    • The quest, and what did not work


    • Build-your-own architecture


    • Revisit contexts


    • Context-driven development

    View Slide

  40. How do I build an application?

    View Slide

  41. Use case
    Adapter
    Infrastructure
    Domain

    View Slide

  42. Adapter
    Infrastructure
    Domain
    Use case
    • Business logic


    • Free of technology

    View Slide

  43. Use case
    Adapter
    Infrastructure
    Domain
    • Use case orchestration


    • Transaction management

    View Slide

  44. Use case
    Adapter
    Infrastructure
    Domain
    • Translation

    View Slide

  45. Use case
    Adapter
    Infrastructure
    Domain
    • External dependency

    • Technical details

    View Slide

  46. Adapter
    Use case
    Infrastructure
    Domain

    View Slide

  47. Clean architecture file structure
    lib


    ├── domain


    ├── use_case


    ├── adapter


    └── infrastructure

    View Slide

  48. Clean architecture file structure
    lib


    ├── domain


    ├── use_case


    ├── adapter


    └── infrastructure
    ├── model


    ├── store (interface)


    └── service


    View Slide

  49. Clean architecture file structure
    lib


    ├── domain


    ├── use_case


    ├── adapter


    └── infrastructure
    ├── upload_image.ex


    └── register_user.ex


    View Slide

  50. Clean architecture file structure
    lib


    ├── domain


    ├── use_case


    ├── adapter


    └── infrastructure
    ├── cli.ex


    ├── web


    └── store

    View Slide

  51. Clean architecture file structure
    lib


    ├── domain


    ├── use_case


    ├── adapter


    └── infrastructure
    ├── cli.ex


    ├── web


    └── store

    View Slide

  52. Clean architecture file structure
    lib


    ├── domain


    ├── use_case


    ├── adapter


    └── infrastructure
    ├── cli.ex


    ├── web


    └── store

    View Slide

  53. Clean architecture file structure
    lib


    ├── domain


    ├── use_case


    ├── adapter


    └── infrastructure
    ├── application.ex


    ├── mailer.ex


    ├── repo.ex


    ├── web


    ├── endpoint.ex


    ├── gettext.ex


    ├── router.ex


    └── telemetry.ex

    View Slide

  54. (Revisit) The cunning challenges of contexts
    • Different layers of concerns are mixed together.


    • Relationships between components are ambiguous.

    View Slide

  55. • Different layers of concerns are mixed together.


    Separation of concerns 👍


    • Relationships between components are ambiguous.

    View Slide

  56. • Different layers of concerns are mixed together.


    Separation of concerns 👍


    • Relationships between components are ambiguous.


    Clear relationship between components 👍

    View Slide

  57. • Different layers of concerns are mixed together.


    Separation of concerns 👍


    • Relationships between components are ambiguous.


    Clear relationship between components 👍


    • Very testable 👍

    View Slide

  58. The almighty clean architecture
    • Separation of concerns


    • Clear relationship between components


    • Very testable

    View Slide

  59. https://media.giphy.com/media/jQnrJSmFB6KVQ7kfpK/giphy.gif

    View Slide

  60. Outline
    • The cunning challenges of contexts


    • The quest, and what did not work


    • Build-your-own architecture


    • Revisit contexts


    • Context-driven development

    View Slide

  61. from Phoenix of
    fi
    cial guide
    “Contexts are dedicated modules that


    expose and group related functionality.“

    View Slide

  62. How can context improve


    our current architecture?

    View Slide

  63. Example: User noti
    fi
    cation
    Use case
    Adapter
    Infrastructure
    Domain

    View Slide

  64. Adapter
    Infrastructure
    Domain
    Use case
    • model/noti
    fi
    cation.ex


    • store/noti
    fi
    cation_store.ex


    • store/user_store.ex
    Example: User noti
    fi
    cation

    View Slide

  65. Use case
    Adapter
    Infrastructure
    Domain
    • notify_user.ex
    Example: User noti
    fi
    cation

    View Slide

  66. Use case
    Adapter
    Infrastructure
    Domain
    • store/user_store.ex


    • store/noti
    fi
    cation_store.ex


    • web/controller/


    noti
    fi
    cation_controller.ex
    Example: User noti
    fi
    cation

    View Slide

  67. Improve current architecture with context
    • domain/model/noti
    fi
    cation.ex


    • domain/store/noti
    fi
    cation_store.ex


    • domain/store/user_store.ex


    • use_case/notify_user.ex


    • adapter/store/noti
    fi
    cation_store.ex


    • adapter/store/user_store.ex


    • adapter/web/controller/noti
    fi
    cation_controller.ex

    View Slide

  68. • domain/model/noti
    fi
    cation.ex


    • domain/store/noti
    fi
    cation_store.ex


    • domain/store/user_store.ex


    • use_case/notify_user.ex


    • adapter/store/noti
    fi
    cation_store.ex


    • adapter/store/user_store.ex


    • adapter/web/controller/noti
    fi
    cation_controller.ex
    Improve current architecture with context

    View Slide

  69. • domain/model/noti
    fi
    cation.ex


    • domain/model/user.ex


    • domain/store/noti
    fi
    cation_store.ex


    • domain/store/user_store.ex


    • use_case/notify_user.ex


    • adapter/store/noti
    fi
    cation_store.ex


    • adapter/store/user_store.ex


    • adapter/web/controller/noti
    fi
    cation_controller.ex
    Improve current architecture with context

    View Slide

  70. • domain/model/noti
    fi
    cation.ex


    • domain/model/user.ex


    • domain/store/noti
    fi
    cation_store.ex


    • domain/store/user_store.ex


    • use_case/notify_user.ex


    • adapter/store/noti
    fi
    cation_store.ex


    • adapter/store/user_store.ex


    • adapter/web/controller/noti
    fi
    cation_controller.ex
    Improve current architecture with context

    View Slide

  71. Adapter
    Use case
    Infrastructure
    Domain

    View Slide

  72. Adapter
    Use case
    Infrastructure
    Domain

    View Slide

  73. Apply context
    Adapter Use case
    Infrastructure Domain

    View Slide

  74. Apply contexts
    Adapter Use case
    Infrastructure Domain
    External Internal

    View Slide

  75. Apply contexts
    Adapter Use case
    Infrastructure Domain
    External Internal

    View Slide

  76. Apply contexts
    Internal
    Use case
    Domain

    View Slide

  77. Apply contexts
    Internal
    Use case
    Domain
    Context

    View Slide

  78. Apply contexts
    Use case
    Domain
    Context YourApp.[Context]
    YourApp.[Context].[UseCase]
    YourApp.[Context].[Domain]

    View Slide

  79. Apply contexts
    Use case
    Domain
    Context Noti
    fi
    cation

    Noti
    fi
    cation.notify_user

    Noti
    fi
    cation.Noti
    fi
    cation

    Noti
    fi
    cation.UserStore

    Noti
    fi
    cation.Noti
    fi
    cationStore

    View Slide

  80. Apply contexts
    Use case
    Domain
    Context Noti
    fi
    cation
    Noti
    fi
    cation.notify_user

    Noti
    fi
    cation.Noti
    fi
    cation

    Noti
    fi
    cation.UserStore

    Noti
    fi
    cation.Noti
    fi
    cationStore

    View Slide

  81. Apply contexts
    Use case
    Domain
    Context Noti
    fi
    cation
    Noti
    fi
    cation.notify_user
    Noti
    fi
    cation.Noti
    fi
    cation

    Noti
    fi
    cation.UserStore

    Noti
    fi
    cation.Noti
    fi
    cationStore

    View Slide

  82. Apply contexts
    Use case
    Domain
    Context Noti
    fi
    cation
    Noti
    fi
    cation.notify_user
    Noti
    fi
    cation.Noti
    fi
    cation
    Noti
    fi
    cation.UserStore

    Noti
    fi
    cation.Noti
    fi
    cationStore

    View Slide

  83. File structure
    ├── noti
    fi
    cation


    │ ├── noti
    fi
    cation.ex


    │ ├── noti
    fi
    cation_store.ex


    │ └── user_store.ex


    └── noti
    fi
    cation.ex


    View Slide

  84. File structure
    ├── noti
    fi
    cation


    │ ├── noti
    fi
    cation.ex


    │ ├── noti
    fi
    cation_store.ex


    │ └── user_store.ex


    └── noti
    fi
    cation.ex


    # context

    View Slide

  85. ├── noti
    fi
    cation


    │ ├── noti
    fi
    cation.ex


    │ ├── noti
    fi
    cation_store.ex


    │ └── user_store.ex


    └── noti
    fi
    cation.ex
    File structure

    View Slide

  86. ├── noti
    fi
    cation


    │ ├── noti
    fi
    cation.ex


    │ ├── noti
    fi
    cation_store.ex


    │ └── user_store.ex


    └── noti
    fi
    cation.ex
    File structure

    View Slide

  87. ├── noti
    fi
    cation


    │ ├── noti
    fi
    cation.ex


    │ ├── noti
    fi
    cation_store.ex


    │ └── user_store.ex


    └── noti
    fi
    cation.ex
    File structure

    View Slide

  88. ├── noti
    fi
    cation


    │ ├── noti
    fi
    cation.ex


    │ ├── noti
    fi
    cation_store.ex


    │ └── user_store.ex


    └── noti
    fi
    cation.ex
    File structure

    View Slide

  89. ├── noti
    fi
    cation


    │ ├── noti
    fi
    cation.ex


    │ ├── noti
    fi
    cation_store.ex


    │ └── user_store.ex


    └── noti
    fi
    cation.ex
    File structure

    View Slide

  90. ├── noti
    fi
    cation


    │ ├── noti
    fi
    cation.ex


    │ ├── noti
    fi
    cation_store.ex


    │ └── user_store.ex


    └── noti
    fi
    cation.ex
    File structure

    View Slide

  91. ├── noti
    fi
    cation


    │ ├── noti
    fi
    cation.ex


    │ ├── noti
    fi
    cation_store.ex


    │ └── user_store.ex


    └── noti
    fi
    cation.ex
    File structure

    View Slide

  92. ├── noti
    fi
    cation


    │ ├── noti
    fi
    cation.ex


    │ ├── noti
    fi
    cation_store.ex


    │ └── user_store.ex


    └── noti
    fi
    cation.ex
    File structure

    View Slide

  93. ├── noti
    fi
    cation


    │ ├── noti
    fi
    cation.ex


    │ ├── noti
    fi
    cation_store.ex


    │ └── user_store.ex


    └── noti
    fi
    cation.ex
    File structure

    View Slide

  94. ├── noti
    fi
    cation


    │ ├── noti
    fi
    cation.ex


    │ ├── noti
    fi
    cation_store.ex


    │ └── user_store.ex


    └── noti
    fi
    cation.ex
    File structure

    View Slide

  95. ElixirLab
    Noti
    fi
    cation
    Account
    Cross-context relationship

    View Slide

  96. ElixirLab
    Noti
    fi
    cation
    Account
    Account.create_user Noti
    fi
    cation.not
    fi
    y_new_user
    Cross-context relationship

    View Slide

  97. ElixirLab
    Noti
    fi
    cation
    Account
    Cross-context relationship: Implicit dependency?
    depends on

    View Slide

  98. ElixirLab
    Noti
    fi
    cation
    Account
    Cross-context relationship
    depends on depends on

    View Slide

  99. ├── noti
    fi
    cation


    │ ├── noti
    fi
    cation.ex


    │ ├── noti
    fi
    cation_store.ex


    │ └── user_store.ex


    └── noti
    fi
    cation.ex
    The external layer

    View Slide

  100. elixir_lab


    ├── noti
    fi
    cation


    │ ├── noti
    fi
    cation.ex


    │ ├── noti
    fi
    cation_store.ex


    │ └── user_store.ex


    └── noti
    fi
    cation.ex
    The external layer

    View Slide

  101. elixir_lab


    ├── noti
    fi
    cation


    │ ├── noti
    fi
    cation.ex


    │ ├── noti
    fi
    cation_store.ex


    │ └── user_store.ex


    └── noti
    fi
    cation.ex
    elixir_lab_external


    ├── noti
    fi
    cation_store.ex


    ├── repo


    │ ├── schema


    │ └── user_repo.ex


    ├── web (Phoenix)
    The external layer

    View Slide

  102. elixir_lab


    ├── noti
    fi
    cation


    │ ├── noti
    fi
    cation.ex


    │ ├── noti
    fi
    cation_store.ex


    │ └── user_store.ex


    └── noti
    fi
    cation.ex
    elixir_lab_external


    ├── noti
    fi
    cation_store.ex


    ├── repo


    │ ├── schema


    │ └── user_repo.ex


    ├── web (Phoenix)
    The external layer

    View Slide

  103. • Separation of concerns


    • Clear relationship between components


    • Very testable
    Result of applying context

    View Slide

  104. • Separation of concerns


    • Clear relationship between components


    • Very testable


    • Groups related functionality together 👍
    Result of applying context

    View Slide

  105. Outline
    • The cunning challenges of contexts


    • The quest, and what did not work


    • Build-your-own architecture


    • Revisit contexts


    • Context-driven development 🏁

    View Slide

  106. Context-driven development
    • Separate your business concerns.

    View Slide

  107. Context-driven development
    • Separate your business concerns.


    • Take advantage of Elixir’s
    fl
    exibility.

    View Slide

  108. Context-driven development
    • Separate your business concerns.


    • Take advantage of Elixir’s
    fl
    exibility.


    • But use it carefully.

    View Slide

  109. Context-driven development
    • Separate your business concerns.


    • Take advantage of Elixir’s
    fl
    exibility.


    • But use it carefully.


    • Make your architecture scream.

    View Slide

  110. source: https://tenor.com/view/chubby-chubby-cat-stuck-door-pet-door-gif-5518148
    Phoenix Your application

    View Slide

  111. source: http://gph.is/1eeJ98k?tc=1
    Phoenix Your application

    View Slide

  112. Resources
    Books
    • Clean Architecture: A Craftsman's Guide to Software Structure by
    Robert C. Martin


    • Functional Web Development with Elixir, OTP, and Phoenix by by
    Lance Halvorsen


    • Domain Modeling Made Functional by Scott Wlaschin


    • Implementing Domain-Driven Design by Vaughn Vernon


    • Programming Phoenix by Bruce Tate, Chris McCord and José Valim

    View Slide

  113. Resources
    Videos
    • Building Beautiful Systems with Phoenix Contexts and DDD by
    Andrew Hao


    • Lonestar ElixirConf 2017- KEYNOTE: Phoenix 1.3 by Chris McCord


    • Ruby Midwest 2011 - Keynote: Architecture the Lost Years by
    Robert Martin

    View Slide

  114. Resources
    Articles / Blog posts / Forum questions
    • https://hexdocs.pm/phoenix/contexts.html


    • https://elixirforum.com/t/hexagonal-architecture-in-elixir/32225/16


    • https://elixirforum.com/t/how-to-determine-contexts-with-phoenix-1-3/4367


    • https://aaronrenner.io/2019/09/18/application-layering-a-pattern-for-extensible-
    elixir-application-design.html


    • https://www.destroyallsoftware.com/screencasts/catalog/functional-core-
    imperative-shell


    • https://blog.cleancoder.com

    View Slide

  115. https://github.com/jenny-codes/elixirlab
    @jenny_codes

    View Slide