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

A Practical Introduction to Domain Driven Design

A Practical Introduction to Domain Driven Design

pelshoff

May 14, 2019
Tweet

More Decks by pelshoff

Other Decks in Research

Transcript

  1. Please tell 2 others:
    1. Why you are here today
    2. What you want from today
    3. To take a look at
    github.com/pelshoff/intro-ddd

    View Slide

  2. A Practical
    Introduction
    To Domain Driven Design
    Twitter: @pelshoff @jlammerts

    View Slide

  3. ● has a cult following
    ● works in all cases
    ● only works if everyone commits
    ● takes a lot more time
    ● is only for experienced
    developers
    ● goes well with event sourcing
    ● doesn’t work without event
    sourcing

    ● is about documentation
    ● is a new concept
    ● is about strategy
    ● is about tactics
    ● is only for developers
    ● is a hype
    ● is for every project
    ● is all-or-nothing
    ● is about language

    DDD... (true / false)

    View Slide

  4. View Slide

  5. Approach
    ● Reality
    ● Model of the problem
    ● Model of the solution
    ● Working software

    View Slide

  6. Today
    1. Discovery
    2. Design
    3. Implementation
    4. Integration

    View Slide

  7. 1/4 Discovery

    View Slide

  8. View Slide

  9. Noun
    Verb Verb
    Verb
    Verb
    Noun
    Noun
    Noun
    Noun

    View Slide

  10. Context map
    ● Repeat before interpret
    ● Visualize structure
    ● Learn (ubiquitous) language
    ● First “feeling” for boundaries

    View Slide

  11. Organizer
    Plans
    Event
    github.com/pelshoff/
    Intro-ddd
    #User interviews
    ● Organizer plans event
    ● Organizer gets in touch with suppliers
    ● etc.

    View Slide

  12. Testing
    ● Take one sentence
    ● Run it through your map

    View Slide

  13. View Slide

  14. Event Event Event Event
    Event
    Event Event
    Event
    Hot spot
    Decision

    View Slide

  15. Discovery event
    storm
    ● First interpretation
    ● Visualize time
    ● Learn (ubiquitous) language
    ● Learn about issues (hot spots)
    ● First “feeling” for boundaries

    View Slide

  16. github.com/pelshoff/
    Intro-ddd
    #User interviews
    ● Event was planned
    ● Suppliers were contacted
    ● etc.
    Event Decision Hot spot
    Member was
    invoiced
    14 days
    passed
    Invoice was
    paid
    Reminder
    was sent
    Including
    Sundays?
    Visitor
    arrived
    Has voting
    privileges
    Seated
    non-voting
    Seated
    voting
    How do we
    know?

    View Slide

  17. Testing
    ● Take a person
    ● What happens to them
    ● Run it through your process

    View Slide

  18. 2/4 Design

    View Slide

  19. Design
    ● Design event storm
    ● Choosing boundaries

    View Slide

  20. View Slide

  21. Command Event Event Event
    Event
    Event
    Event
    ...
    Command Decision
    Command

    View Slide

  22. github.com/pelshoff/
    Intro-ddd
    #User interviews
    ● Event was planned
    ● Suppliers were contacted
    ● etc.
    Event Decision
    Member was
    invoiced
    Command
    Send
    invoices
    Reminder
    was planned

    View Slide

  23. Testing
    ● Take a person
    ● What they do
    ● Run it through your process

    View Slide

  24. 3/4 Implementation

    View Slide

  25. View Slide

  26. Command

    View Slide

  27. final class DoVote {
    private $decisionId;
    ...
    public function __construct(Uuid $decisionId, Uuid $memberId, Answer $answer) {
    $this->decisionId = $decisionId;
    $this->memberId = $memberId;
    $this->answer = $answer;
    }
    public function getDecisionId(): Uuid {
    return $this->decisionId;
    }
    ...
    }

    View Slide

  28. Command
    ● Data Transfer Object
    ● Immutable
    ● Capture intention

    View Slide

  29. Command handler

    View Slide

  30. final class DoVoteHander {
    public function handleDoVote(DoVote $doVote): void {
    // Voted
    // DecisionWasPassed
    // DecisionWasRejected
    }
    }

    View Slide

  31. Command handler
    ● Application Entry Point
    ● When command, then event(s)
    ● Implementation later

    View Slide

  32. Work out some
    commands in code
    ● Create command DTO’s
    ● Create empty command handlers
    ● Add comments for events
    No implementation!
    No framework!
    Get something started
    One service per command
    Use and adapt the event storm model
    Group project files by context

    View Slide

  33. View Slide

  34. Value objects

    View Slide

  35. final class Name {
    private $lastName;
    private $firstName;
    private $insertion;
    public function __construct(string $lastName, string $firstName, string $insertion) {
    $this->lastName = $lastName;
    $this->firstName = $firstName;
    $this->insertion = $insertion;
    $this->nameMustHaveLastName();
    }
    private function nameMustHaveLastName(): void {
    if (!$this->lastName) {
    throw InvalidName::becauseLastNameIsMissing();
    }
    }
    public function getLastName(): string { /**/ }
    public function getFirstName(): string { /**/ }
    public function getInsertion(): string { /**/ }
    }

    View Slide

  36. final class EmailAddress {
    private $emailAddress;
    public function __construct(string $emailAddress) {
    $this->emailAddress = $emailAddress;
    $this->emailAddressMustBeAnActualEmailAddress();
    }
    private function emailAddressMustBeAnActualEmailAddress(): void {
    if (!filter_var($this->emailAddress, FILTER_VALIDATE_EMAIL)) {
    throw InvalidEmailAddress::becauseThisIsNotAnEmailAddress();
    }
    }
    public function asString(): string {
    return $this->emailAddress;
    }
    }

    View Slide

  37. Value objects
    ● Express a value
    ● Define allowed values
    ● Are immutable
    ● Are easy to test

    View Slide

  38. Entities

    View Slide

  39. final class Member {
    private $id;
    private $name;
    private $emailAddress;
    public function __construct(Uuid $id, Name $name, EmailAddress $emailAddress) {
    $this->id = $id;
    $this->name = $name;
    $this->emailAddress = $emailAddress;
    }
    public function getId(): Uuid { /**/ }
    public function getName(): Name { /**/ }
    public function setName(Name $name): Attendee { /**/ }
    public function getEmailAddress(): EmailAddress { /**/ }
    public function setEmailAddress(EmailAddress $emailAddress): Attendee {
    $this->emailAddress = $emailAddress;
    return $this;
    }
    }

    View Slide

  40. Entities
    ● Have identity
    ● Are more than their attributes
    ● Evolve over time
    ● Are slightly harder to test

    View Slide

  41. Services

    View Slide

  42. final class VotingOnDecision {
    private $repository;
    public function __construct(VoteRepository $repository) {
    $this->repository = $repository;
    }
    public function handleDoVote(DoVote $doVote): void {
    $this->memberMayOnlyVoteOnce($doVote);
    $this->repository->register($doVote);
    }
    private function memberMayOnlyVoteOnce(DoVote $doVote): void {
    try {
    $this->repository->find($doVote->getDecisionId(), $doVote->getMemberId());
    } catch (VoteNotFound $e) {
    return;
    }
    throw VotingFailed::becauseMemberAlreadyVotedOnDecision();
    }
    }

    View Slide

  43. Services
    ● Have no identity or attributes
    (Are not a “thing”)
    ● Tackle cross-concern operations
    ● Are harder to test

    View Slide

  44. Repositories

    View Slide

  45. interface VoteRepository{
    public function register(DoVote $doVote): void;
    public function find(Uuid $decisionId, Uuid $memberId): Member;
    }

    View Slide

  46. Repositories
    ● Collection of all objects of a type
    ● For now: interface only!

    View Slide

  47. ● Vendor
    ○ PartyCongress
    ■ Src
    ● Domain
    ○ Congress
    ■ Congress.php
    ■ Decision.php
    ■ ListOfDecisions.php
    ■ Vote.php
    ■ VotingOnDecision.php
    ■ VoteRepository.php
    ○ Invoice
    ■ PaidInvoices.php
    ○ Membership
    ■ Member.php
    ■ MemberRepository.php
    ■ Test
    ● Congress
    ○ CongressTest.php
    ○ DecisionTest.php
    ○ VotingOnDecisionTest.php

    View Slide

  48. Work out the domain in
    code
    ● Value Object: Immutable!
    ● Entity: Life cycle!
    ● Domain Service: Cross-concern process!
    ● Repository: Complete set of a type of entity!
    No database!
    No browser!
    No generic subdomain!
    Focus on the domain
    Write unit tests
    Use and adapt the event storm model
    Group project files by context

    View Slide

  49. 4/4 Integration

    View Slide

  50. View Slide

  51. Domain
    Application
    Infrastructure
    Ui, Api’s, tests
    Layered architecture

    View Slide

  52. Domain
    Application
    Database
    Api’s
    Ui
    Tests
    File system
    Messaging, etc.
    Hexagonal architecture (Ports & Adapters)

    View Slide

  53. Ui, Api’s, integration- & acceptance tests
    Application
    Domain
    Infrastructure
    Big scary
    outside
    world
    Unit
    tests

    View Slide

  54. ● Vendor
    ○ PartyCongress
    ■ Src
    ● App
    ○ Congress
    ■ DoVote.php
    ■ DoVoteHandler.php
    ○ Membership
    ● Domain
    ○ Congress
    ■ Congress.php
    ■ Decision.php
    ■ ListOfDecisions.php
    ■ VoteRepository.php
    ○ Membership
    ● Infrastructure
    ○ Congress
    ■ CachingVoteRepository.php
    ■ InMemoryVoteRepository.php
    ■ Test
    ● Congress
    ○ CongressTest.php
    ○ DecisionTest.php
    ○ VotingTest.php

    View Slide

  55. ● Vendor
    ○ PartyCongress
    ■ Src
    ● App
    ○ Congress
    ■ DoVoteHandler.php
    ● Domain
    ○ Congress
    ■ CongressRepository.php
    ■ VoteRepository.php
    ● Infrastructure
    ○ Congress
    ■ InMemoryCongressRepository.php
    ● MyFrameworkOfChoice
    ○ Bundles
    ■ PartyCongressBundle
    ● Infrastructure
    ○ Congress
    ■ DbalCongressRepository.php
    ■ DbalVoteRepository.php
    ● Ui
    ○ Congress
    ■ OnlineVotingController.php
    ● Test
    ○ Congress
    ■ OnlineVotingFrontEndTest.php

    View Slide

  56. Work out the
    integration in code
    ● Connect the domain to your favorite framework,
    ● Or to Plain-Old-C/PHP/Fortran/?
    ● Make something work from UI to DB and back
    Database
    Browser
    End to end tests
    Group project files by concept

    View Slide

  57. Please write two post-its with
    something you learned
    Pim Elshoff @pelshoff
    Joop Lammerts @jlammerts

    View Slide