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

Context-Driven Development: Architecture your code with Phoenix context

29a4e399a1da465022ca661f9aa2dc36?s=47 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.

29a4e399a1da465022ca661f9aa2dc36?s=128

Jenny Shih

October 12, 2021
Tweet

Transcript

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

  2. None
  3. None
  4. https://media.giphy.com/media/NWtFdrEXGwZX2/giphy.gif

  5. • Quick onboarding

  6. • Quick onboarding • Effective

  7. • Quick onboarding • Effective • Using Elixir

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

  9. What do I do with contexts?

  10. Outline • The cunning challenges of contexts • The quest,

    and what did not work • Build-your-own architecture • Revisit contexts • Context-driven development
  11. Outline • The cunning challenges of contexts • The quest,

    and what did not work • Build-your-own architecture • Revisit contexts • Context-driven development
  12. None
  13. “Contexts are dedicated modules that expose and group related functionality.“

  14. Model Controller View Request Response

  15. Model Controller View /your_app_web /your_app

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

    View /your_app_web /your_app
  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
  18. Phoenix MVC structure lib ├── your_app ├── ??? ├── ???

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

    └── ??? ├── your_app_web Model Controller View /your_app_web /your_app Context
  20. The cunning challenges of contexts

  21. The cunning challenges of contexts • Different layers of concerns

    are mixed together.
  22. None
  23. None
  24. The cunning challenges of contexts

  25. concept of context Ecto business logic juggler by Orin zuu

    from the Noun Project The cunning challenges of contexts
  26. The cunning challenges of contexts • Different layers of concerns

    are mixed together. • Relationships between components are ambiguous.
  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
  28. Outline • The cunning challenges of contexts • The quest,

    and what did not work • Build-your-own architecture • Revisit contexts • Context-driven development
  29. What to do with context? • Look at open-source projects?

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

    • Domain Driven Design?
  31. source: https://youtu.be/tMO28ar0lW8

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

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

  34. None
  35. https://gfycat.com/composedimportantavians

  36. 💡

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

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

    that expose and group related functionality.“
  39. Outline • The cunning challenges of contexts • The quest,

    and what did not work • Build-your-own architecture • Revisit contexts • Context-driven development
  40. How do I build an application?

  41. Use case Adapter Infrastructure Domain

  42. Adapter Infrastructure Domain Use case • Business logic • Free

    of technology
  43. Use case Adapter Infrastructure Domain • Use case orchestration •

    Transaction management
  44. Use case Adapter Infrastructure Domain • Translation

  45. Use case Adapter Infrastructure Domain • External dependency • Technical

    details
  46. Adapter Use case Infrastructure Domain

  47. Clean architecture file structure lib ├── domain ├── use_case ├──

    adapter └── infrastructure
  48. Clean architecture file structure lib ├── domain ├── use_case ├──

    adapter └── infrastructure ├── model ├── store (interface) └── service
  49. Clean architecture file structure lib ├── domain ├── use_case ├──

    adapter └── infrastructure ├── upload_image.ex └── register_user.ex
  50. Clean architecture file structure lib ├── domain ├── use_case ├──

    adapter └── infrastructure ├── cli.ex ├── web └── store
  51. Clean architecture file structure lib ├── domain ├── use_case ├──

    adapter └── infrastructure ├── cli.ex ├── web └── store
  52. Clean architecture file structure lib ├── domain ├── use_case ├──

    adapter └── infrastructure ├── cli.ex ├── web └── store
  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
  54. (Revisit) The cunning challenges of contexts • Different layers of

    concerns are mixed together. • Relationships between components are ambiguous.
  55. • Different layers of concerns are mixed together. Separation of

    concerns 👍 • Relationships between components are ambiguous.
  56. • Different layers of concerns are mixed together. Separation of

    concerns 👍 • Relationships between components are ambiguous. Clear relationship between components 👍
  57. • Different layers of concerns are mixed together. Separation of

    concerns 👍 • Relationships between components are ambiguous. Clear relationship between components 👍 • Very testable 👍
  58. The almighty clean architecture • Separation of concerns • Clear

    relationship between components • Very testable
  59. https://media.giphy.com/media/jQnrJSmFB6KVQ7kfpK/giphy.gif

  60. Outline • The cunning challenges of contexts • The quest,

    and what did not work • Build-your-own architecture • Revisit contexts • Context-driven development
  61. from Phoenix of fi cial guide “Contexts are dedicated modules

    that expose and group related functionality.“
  62. How can context improve our current architecture?

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

  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
  65. Use case Adapter Infrastructure Domain • notify_user.ex Example: User noti

    fi cation
  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
  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
  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
  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
  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
  71. Adapter Use case Infrastructure Domain

  72. Adapter Use case Infrastructure Domain

  73. Apply context Adapter Use case Infrastructure Domain

  74. Apply contexts Adapter Use case Infrastructure Domain External Internal

  75. Apply contexts Adapter Use case Infrastructure Domain External Internal

  76. Apply contexts Internal Use case Domain

  77. Apply contexts Internal Use case Domain Context

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

  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
  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
  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
  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
  83. File structure ├── noti fi cation │ ├── noti fi

    cation.ex │ ├── noti fi cation_store.ex │ └── user_store.ex └── noti fi cation.ex
  84. File structure ├── noti fi cation │ ├── noti fi

    cation.ex │ ├── noti fi cation_store.ex │ └── user_store.ex └── noti fi cation.ex # context
  85. ├── noti fi cation │ ├── noti fi cation.ex │

    ├── noti fi cation_store.ex │ └── user_store.ex └── noti fi cation.ex File structure
  86. ├── noti fi cation │ ├── noti fi cation.ex │

    ├── noti fi cation_store.ex │ └── user_store.ex └── noti fi cation.ex File structure
  87. ├── noti fi cation │ ├── noti fi cation.ex │

    ├── noti fi cation_store.ex │ └── user_store.ex └── noti fi cation.ex File structure
  88. ├── noti fi cation │ ├── noti fi cation.ex │

    ├── noti fi cation_store.ex │ └── user_store.ex └── noti fi cation.ex File structure
  89. ├── noti fi cation │ ├── noti fi cation.ex │

    ├── noti fi cation_store.ex │ └── user_store.ex └── noti fi cation.ex File structure
  90. ├── noti fi cation │ ├── noti fi cation.ex │

    ├── noti fi cation_store.ex │ └── user_store.ex └── noti fi cation.ex File structure
  91. ├── noti fi cation │ ├── noti fi cation.ex │

    ├── noti fi cation_store.ex │ └── user_store.ex └── noti fi cation.ex File structure
  92. ├── noti fi cation │ ├── noti fi cation.ex │

    ├── noti fi cation_store.ex │ └── user_store.ex └── noti fi cation.ex File structure
  93. ├── noti fi cation │ ├── noti fi cation.ex │

    ├── noti fi cation_store.ex │ └── user_store.ex └── noti fi cation.ex File structure
  94. ├── noti fi cation │ ├── noti fi cation.ex │

    ├── noti fi cation_store.ex │ └── user_store.ex └── noti fi cation.ex File structure
  95. ElixirLab Noti fi cation Account Cross-context relationship

  96. ElixirLab Noti fi cation Account Account.create_user Noti fi cation.not fi

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

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

    on
  99. ├── noti fi cation │ ├── noti fi cation.ex │

    ├── noti fi cation_store.ex │ └── user_store.ex └── noti fi cation.ex The external layer
  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
  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
  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
  103. • Separation of concerns • Clear relationship between components •

    Very testable Result of applying context
  104. • Separation of concerns • Clear relationship between components •

    Very testable • Groups related functionality together 👍 Result of applying context
  105. Outline • The cunning challenges of contexts • The quest,

    and what did not work • Build-your-own architecture • Revisit contexts • Context-driven development 🏁
  106. Context-driven development • Separate your business concerns.

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

    of Elixir’s fl exibility.
  108. Context-driven development • Separate your business concerns. • Take advantage

    of Elixir’s fl exibility. • But use it carefully.
  109. Context-driven development • Separate your business concerns. • Take advantage

    of Elixir’s fl exibility. • But use it carefully. • Make your architecture scream.
  110. source: https://tenor.com/view/chubby-chubby-cat-stuck-door-pet-door-gif-5518148 Phoenix Your application

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

  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
  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
  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
  115. https://github.com/jenny-codes/elixirlab @jenny_codes