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

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!

Tom Van Herreweghe

September 27, 2016
Tweet

More Decks by Tom Van Herreweghe

Other Decks in Programming

Transcript

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

    View Slide

  2. OR HOW TO DECOUPLE FROM YOUR FRAMEWORK

    View Slide

  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

    View Slide

  4. © Carlos Buenosvinos
    DDD ARCHITECTURAL STYLES TRIP

    View Slide

  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

    View Slide

  6. Who remembers their reaction when rst being introduced to a
    framework?
    SMALL AMOUNT OF INTERACTION

    View Slide

  7. View Slide

  8. Boils down to
    I Not Understands :'(

    View Slide

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

    View Slide

  10. TO AVOID GENERALIZATIONS, LET ME TRY TO EXPLAIN

    View Slide

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

    View Slide

  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

    View Slide

  13. RESULT
    Infrastructure Agnostic
    Easy To Test
    Easy To Maintain

    View Slide

  14. View Slide

  15. KEYWORDS
    Message
    Port
    Adapter

    View Slide

  16. MESSAGE
    Carries the data of a communication
    Cross boundaries
    Examples: telephone message, fax, letter

    View Slide

  17. PORT
    Enables an incoming message to enter a system
    Examples: telephone horn, letterbox, ears

    View Slide

  18. ADAPTER
    Translate the message to something useful for the system
    Examples: modem, hairs in your ears

    View Slide

  19. HTTP Message ➞ Web Server ➞ PHP-FPM
    CLI Command ➞ PHP Binary ➞ PHP Script
    ALREADY PART OF YOUR APPLICATION

    View Slide

  20. THAT'S IT! DONE!

    View Slide

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

    View Slide

  22. YOUR APPLICATION
    Creates dependencies between components

    View Slide

  23. YOUR APPLICATION
    Stu that makes you money
    The rest

    View Slide

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

    View Slide

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

    View Slide

  26. Framework & Libraries abstract infrastructure details away

    View Slide

  27. YOUR APPLICATION
    Domain
    Infrastructure

    View Slide

  28. View Slide

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

    View Slide

  30. TWO DISTINCT LAYERS
    Boundaries between Domain & Infrastructure

    View Slide

  31. Cross boundaries with
    MESSAGE

    View Slide

  32. CROSSING BOUNDARIES COMES WITH RULES

    View Slide

  33. Dependencies only point inward
    THE DEPENDENCY RULE

    View Slide

  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

    View Slide

  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
    ) {
    /
    / .
    .
    .
    }
    }

    View Slide

  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
    ) {
    /
    / .
    .
    .
    }
    }

    View Slide

  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
    ) {
    /
    / .
    .
    .
    }
    }

    View Slide

  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

    View Slide

  39. HOW?

    View Slide

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

    View Slide

  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
    ;
    }
    }

    View Slide

  42. PORT & ADAPTER
    ⇨ HANDLER
    Receives a Message/Command
    Knows what to do with it

    View Slide

  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
    )
    ;
    }
    }

    View Slide

  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

    View Slide

  45. Receive Command
    Match Handler
    Centralized con guration
    Middlewares
    COMMAND BUS

    View Slide

  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
    }
    }

    View Slide

  47. Slim controllers
    Infrastructure independent / Reusable
    Easily testable
    Easy to maintain
    OVERENGINEERD?

    View Slide

  48. TIPS / CONSIDERATIONS

    View Slide

  49. They don't return things
    COMMANDS CHANGE THINGS

    View Slide

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

    View Slide

  51. GENERATE NECESSARY STUFF OUTSIDE HANDLER

    View Slide

  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
    )
    ;
    }

    View Slide

  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

    View Slide

  54. No immediate result
    May require changes to your code
    ASSUME COMMAND'S ARE PUT ON A QUEUE

    View Slide

  55. ! THE DEPENDENCY RULE !

    View Slide

  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

    View Slide

  57. THANK YOU!

    View Slide

  58. QUESTIONS?

    View Slide

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

    View Slide