Hexagonal Architecture, or how to completely overengineer your application

Hexagonal Architecture, or how to completely overengineer your application

With this slidedeck, I try to explain what Hexagonal Architecture is. The main goal is to increase you knowledge about the subject, so that unfounded generalisations based on ignorance are a thing from the past!

9227671c02701253b64e469823671635?s=128

Tom Van Herreweghe

September 27, 2016
Tweet

Transcript

  1. HEXAGONAL ARCHITECTURE OR HOW TO COMPLETELY OVER-ENGINEER YOUR APPLICATION

  2. OR HOW TO DECOUPLE FROM YOUR FRAMEWORK

  3. ON THE MENU TODAY An Introduction Small Amount of Interaction

    Mainly Me, Explaining Things Illustrated By Some Code An O er of Links and Tools Small Amount of Interaction
  4. © Carlos Buenosvinos DDD ARCHITECTURAL STYLES TRIP

  5. Who considers themselves still at the spaguetti level? Who considers

    themselves at the framework level? Who considers themselves at a further level? SMALL AMOUNT OF INTERACTION
  6. Who remembers their reaction when rst being introduced to a

    framework? SMALL AMOUNT OF INTERACTION
  7. None
  8. Boils down to I Not Understands :'(

  9. Boils down to OVER-ENGINEERING!! (or any other generalization)

  10. TO AVOID GENERALIZATIONS, LET ME TRY TO EXPLAIN

  11. Ports & Adapters Message Oriented Architecture 2005, Alistair Cockburn HEXAGONAL

    ARCHITECTURE
  12. The Hexagonal Architecture allows an application to be equally driven

    by users, programs, automated tests or batch scripts, and to be developed and tested in isolation from its eventual run-time devices and databases
  13. RESULT Infrastructure Agnostic Easy To Test Easy To Maintain

  14. None
  15. KEYWORDS Message Port Adapter

  16. MESSAGE Carries the data of a communication Cross boundaries Examples:

    telephone message, fax, letter
  17. PORT Enables an incoming message to enter a system Examples:

    telephone horn, letterbox, ears
  18. ADAPTER Translate the message to something useful for the system

    Examples: modem, hairs in your ears
  19. HTTP Message ➞ Web Server ➞ PHP-FPM CLI Command ➞

    PHP Binary ➞ PHP Script ALREADY PART OF YOUR APPLICATION
  20. THAT'S IT! DONE!

  21. YOUR APPLICATION Uses framework Uses libraries (composer anyone?)

  22. YOUR APPLICATION Creates dependencies between components

  23. YOUR APPLICATION Stu that makes you money The rest

  24. YOUR APPLICATION Essential part Non-essential part ↳ Framework, libraries, DB,

    Message Queue, ...
  25. THE ESSENTIAL PART DOES NOT CARE ABOUT THE NON-ESSENTIAL DETAILS

  26. Framework & Libraries abstract infrastructure details away

  27. YOUR APPLICATION Domain Infrastructure

  28. None
  29. Is about separating your domain from your infrastructure HEXAGONAL ARCHITECTURE

  30. TWO DISTINCT LAYERS Boundaries between Domain & Infrastructure

  31. Cross boundaries with MESSAGE

  32. CROSSING BOUNDARIES COMES WITH RULES

  33. Dependencies only point inward THE DEPENDENCY RULE

  34. (or how to not leak infrastructure details) Depend on I

    n t e r f a c e Inject concrete implementation THE DEPENDENCY INVERSION PRINCIPLE
  35. < ? p h p n a m e s

    p a c e F o o \ B a r \ D o m a i n \ S e r v i c e ; u s e F o o \ B a r \ I n f r a s t r u c t u r e \ R e p o s i t o r y \ U s e r M y S q l R e p o s i t o r y ; c l a s s U s e r S e r v i c e { p u b l i c f u n c t i o n _ _ c o n s t r u c t ( U s e r M y S q l R e p o s i t o r y $ r e p o ) { / / . . . } }
  36. < ? p h p n a m e s

    p a c e F o o \ B a r \ D o m a i n \ S e r v i c e ; u s e F o o \ B a r \ D o m a i n \ R e p o s i t o r y \ U s e r R e p o s i t o r y ; c l a s s U s e r S e r v i c e { p u b l i c f u n c t i o n _ _ c o n s t r u c t ( U s e r R e p o s i t o r y $ r e p o ) { / / . . . } }
  37. < ? p h p n a m e s

    p a c e F o o \ B a r \ I n f r a s t r u c t u r e \ R e p o s i t o r y \ U s e r M y S q l R e p o s i t o r y ; u s e F o o \ B a r \ D o m a i n \ R e p o s i t o r y \ U s e r R e p o s i t o r y ; c l a s s U s e r M y S q l R e p o s i t o r y i m p l e m e n t s U s e r R e p o s i t o r y { p u b l i c f u n c t i o n _ _ c o n s t r u c t ( U s e r R e p o s i t o r y $ r e p o ) { / / . . . } }
  38. Create a Message in the Infrastructure layer Use a Port

    to get it to the Domain layer An Adapter creates something useful ↳ Your Domain code CROSSING BOUNDARIES IN YOUR APPLICATION
  39. HOW?

  40. MESSAGE ⇨ COMMAND Contains only data Name expresses intent Suggests

    a change Repeatable
  41. < ? p h p c l a s s

    S a v e B l o g P o s t { p r i v a t e $ t i t l e ; p r i v a t e $ c o n t e n t ; p r i v a t e $ t a g s = [ ] ; p u b l i c f u n c t i o n _ _ c o n s t r u c t ( $ t i t l e , $ c o n t e n t , $ t a g s ) { $ t h i s - > t i t l e = $ t i t l e ; $ t h i s - > c o n t e n t = $ c o n t e n t ; $ t h i s - > t a g s = $ t a g s ; } }
  42. PORT & ADAPTER ⇨ HANDLER Receives a Message/Command Knows what

    to do with it
  43. < ? p h p c l a s s

    S a v e B l o g P o s t H a n d l e r { p r i v a t e $ r e p o ; p u b l i c f u n c t i o n _ _ c o n s t r u c t ( B l o g P o s t R e p o s i t o r y $ r e p o ) { $ t h i s - > r e p o = $ r e p o ; } p u b l i c f u n c t i o n h a n d l e ( S a v e B l o g P o s t $ c o m m a n d ) { $ p o s t = B l o g P o s t : : c r e a t e N e w ( $ c o m m a n d - > g e t T i t l e ( ) , $ c o m m a n d - > g e t C o n t e n t ( ) ) ; $ p o s t - > a d d T a g s ( $ c o m m a n d - > g e t T a g s ( ) ) ; $ t h i s - > r e p o - > a d d ( $ p o s t ) ; } }
  44. < ? p h p c l a s s

    B l o g A d m i n C o n t r o l l e r e x t e n d s B a s e C o n t r o l l e r { p u b l i c f u n c t i o n c r e a t e A c t i o n ( $ r e q u e s t ) { / / c r e a t e f o r m e t c . i f ( $ r e q u e s t - > i s P o s t ( ) ) { $ c o m m a n d = n e w S a v e B l o g P o s t ( $ r e q u e s t - > g e t ( ' t i t l e ' ) , $ r e q u e s t - > g e t ( ' c o n t e n t ' ) , $ r e q u e s t - > g e t ( ' t a g s ' , [ ] ) ) ; $ h a n d l e r = $ t h i s - > g e t ( ' s a v e _ b l o g p o s t _ h a n d l e r ' ) ; $ h a n d l e r - > h a n d l e ( $ c o m m a n d ) ; $ r e s p o n s e - > r e d i r e c t ( ' / f o o ' ) ; } / / d i s p l a y t e m p l a t e
  45. Receive Command Match Handler Centralized con guration Middlewares COMMAND BUS

  46. < ? p h p c l a s s

    B l o g A d m i n C o n t r o l l e r { p u b l i c f u n c t i o n c r e a t e A c t i o n ( $ r e q u e s t ) { / / c r e a t e f o r m e t c . i f ( $ r e q u e s t - > i s P o s t ( ) ) { $ c o m m a n d = n e w S a v e B l o g P o s t ( $ r e q u e s t - > g e t ( ' t i t l e ' ) , $ r e q u e s t - > g e t ( ' c o n t e n t ' ) , $ r e q u e s t - > g e t ( ' t a g s ' , [ ] ) ) ; $ t h i s - > c o m m a n d B u s - > h a n d l e ( $ c o m m a n d ) ; $ r e s p o n s e - > r e d i r e c t ( ' / f o o ' ) ; } / / d i s p l a y t e m p l a t e } }
  47. Slim controllers Infrastructure independent / Reusable Easily testable Easy to

    maintain OVERENGINEERD?
  48. TIPS / CONSIDERATIONS

  49. They don't return things COMMANDS CHANGE THINGS

  50. But how can you get the thing you just created?

  51. GENERATE NECESSARY STUFF OUTSIDE HANDLER

  52. < ? p h p c l a s s

    B l o g A d m i n C o n t r o l l e r { p u b l i c f u n c t i o n c r e a t e A c t i o n ( $ r e q u e s t ) { / / c r e a t e f o r m e t c . i f ( $ r e q u e s t - > i s P o s t ( ) ) { $ i d = $ t h i s - > g e n e r a t o r - > g e n e r a t e I d ( ) ; $ c o m m a n d = n e w S a v e B l o g P o s t ( $ i d , $ r e q u e s t - > g e t ( ' t i t l e ' ) , $ r e q u e s t - > g e t ( ' c o n t e n t ' ) , $ r e q u e s t - > g e t ( ' t a g s ' , [ ] ) ) ; $ t h i s - > c o m m a n d B u s - > h a n d l e ( $ c o m m a n d ) ; $ r e s p o n s e - > r e d i r e c t ( ' / d e t a i l s / ' . $ i d ) ; }
  53. C r e a t e U s e r

    & E d i t U s e r ⇨ S a v e U s e r Reusable Easier to maintain SMART NAMING
  54. No immediate result May require changes to your code ASSUME

    COMMAND'S ARE PUT ON A QUEUE
  55. ! THE DEPENDENCY RULE !

  56. Allistair Cockburn - Hexagonal Architecture - http://alistair.cockburn.us/Hexagonal+architecture Tactician - Command

    Bus - https://tactician.thephpleague.com/ SimpleBus - Command Bus & more - http://simplebus.github.io/MessageBus/ Matthias Noback - Slides PHPBenelux 2016 DDD in PHP - https://leanpub.com/ddd-in-php TOOLS / LIBRARIES
  57. THANK YOU!

  58. QUESTIONS?

  59. HTTPS://LEGACY.JOIND.IN/19077