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 full-size slide

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

    View full-size 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 full-size slide

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

    View full-size slide

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

    View full-size slide

  6. 1/4 Discovery

    View full-size slide

  7. Noun
    Verb Verb
    Verb
    Verb
    Noun
    Noun
    Noun
    Noun

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  11. Event Event Event Event
    Event
    Event Event
    Event
    Hot spot
    Decision

    View full-size slide

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

    View full-size slide

  13. 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 full-size slide

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

    View full-size slide

  15. Design
    ● Design event storm
    ● Choosing boundaries

    View full-size slide

  16. Command Event Event Event
    Event
    Event
    Event
    ...
    Command Decision
    Command

    View full-size slide

  17. 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 full-size slide

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

    View full-size slide

  19. 3/4 Implementation

    View full-size slide

  20. 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 full-size slide

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

    View full-size slide

  22. Command handler

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  25. 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 full-size slide

  26. Value objects

    View full-size slide

  27. 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 full-size slide

  28. 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 full-size slide

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

    View full-size slide

  30. 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 full-size slide

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

    View full-size slide

  32. 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 full-size slide

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

    View full-size slide

  34. Repositories

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  37. ● 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 full-size slide

  38. 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 full-size slide

  39. 4/4 Integration

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  43. ● 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 full-size slide

  44. ● 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 full-size slide

  45. 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 full-size slide

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

    View full-size slide