Practical DDD
@Bauno
Disclaimer
...and so it begins...
- Libro di Evans del 2004
- Descrive (prescrive?) un insieme
di patterns e metodologie di
analisi e implementazione
“Talk is cheap, show me the code”
“DDD...show me the code”
@emadb, 2011
DDD Purpose
● To build a domain (business) model, NOT a data model (anaemic domain)
● To express domain concepts in the code
● To make the implicit explicit (including, but not limited to, errors)
Strategic tools
● Ubiquitous language (Domain experts)
● Bounded context
● Core domain (distillation)
Bounded context
● It’s impossible to build and
maintain a model for a large,
complex organization: divide et
impera
● The preferred way of
communication between
bounded contexts is using Domain
Events via pub/sub
Ubiquitous language
● Rigourous language, no ambiguity
● It’s the language we use in the code, to name our domain concepts
● Usually valid only inside a bounded context
Core domain distillation
● DDD is expensive both in analysis and implementation, so it’s important
to know where to use it
● Every large domain has various supporting subdomains for every core
domain
● Usually found following the money :-)
Tactical tools
● Entities
● Aggregates
● Value Objects
● Domain services
● Domain events
● Repositories
● Factories (anti corruption layer)
Entities and Aggregates
● An entity is just a PO(C|J)O object that
expresses a domain concept and
enforces the domain invariant(s)
● Persistence ignorance
● Holds the business logic of the domain
and its state
● Has an identity throughout the
bounded context (Identity equality)
● An aggregate is a transaction
boundary consisting in several entities
held together by an aggregate root
Value Objects
● Plain simple records
● Immutable
● Structural equality (no identity)
Entities vs Value Objects
● Should this be and Entity or a Value Object? The answer can be subtle or
obvious, and depends mostly on the context
● Usually in a 70/30 ratio
Domain Services
● “The operation relates to a domain concept that is not a natural part of an
Entity or Value Object”
● First class citizens of the domain
● Stateless
Domain Events
● “Nel dominio è successo qualcosa di interessante per un domain expert”
● Can (asynchronously) cross the boundaries of an aggregate
● Compensating events
Repositories
● A repository is a class whose sole purpose is to collaborate with an entity for
data persistence
● SRP is enforced
● Emphasys on the data access pattern, which is made explicit
Factories/Validators
● Responsibles for creating the entities
● Anti corruption layer
● The domain has to be always valid, creating entities in invalid state must
be impossible
● Usually there is a strong coupling between factories and the entities they
create, but that’s ok.
Resulting
architecture
Warning: wrong place for domain
services
Testing
● The core domain has to be
unit tested, ideally with a
100% coverage
● I usually test factories and
repositories in integration
CQS (Command-Query Separation)
CQRS (Command Query Responsibility Separation)
DDD + CQ(R)S
● Only way I’ve found to write a reliable, rock solid DOMAIN model
● Domain Entities
○ Enforces invariants
○ Express business model, relationships
○ Have only public methods
○ They’re the write part of the model
● Views
○ Used for queries:
○ Very dumb, no business logic (only a little, if any, of presentation logic)
○ They’re read-only for the domain (i.e.: they come out, never go in)
○ Tailored to the specific user view (there are A LOT of views, but that’s ok)
How I do it (with a single RDBMS)
public interface IDbDto<DTO> {
TDto ToDto();
void Load(TDto dto);
}
- Dtos are the ONLY data saved to and loaded from the database
- The interface is hidden until we do a cast (which can only be done in the repository)
- The Dtos are used to hydrate (fill the data in) the views and the entities alike
Every entity explicitly implements the interface IDbDto
● Very dumb class
● No constructor
● Everything is public
● Usually denormalized
● Read-only for the domain
● Constructor sets the identity
● Class enforces domain invariants
● No public properties (even read-only)
● Public methods only
● State is completely private
public class Cart : IDbDto<CartDto>
{
public Guid Id {get; }
public Cart (Customer
customer);
public Unit AddItem(Item item);
public Unit CheckOut();
}
public class CartView
{
public ItemView[] Items {get; set}
public string CustomerName {get;
set;}
public string CustomerAddress {get;
set;}
public double Amount {get; set;}
}
public class CartDto
{
public Guid Id {get; set}
public Guid CustomerId {get;
set}
public ItemDto[] Items;
}
● Another dumb class
● Usually Normalized
● No constructor, public
● This is where an ORM
may be handy
Functional DDD
● Really? It’s intrinsically anaemic (Record + Services)
● CQRS (State as application of a series of events) fits better
Questions?
?

Practical domain driven design

  • 1.
  • 2.
  • 3.
    ...and so itbegins... - Libro di Evans del 2004 - Descrive (prescrive?) un insieme di patterns e metodologie di analisi e implementazione
  • 4.
    “Talk is cheap,show me the code” “DDD...show me the code” @emadb, 2011
  • 5.
    DDD Purpose ● Tobuild a domain (business) model, NOT a data model (anaemic domain) ● To express domain concepts in the code ● To make the implicit explicit (including, but not limited to, errors)
  • 6.
    Strategic tools ● Ubiquitouslanguage (Domain experts) ● Bounded context ● Core domain (distillation)
  • 7.
    Bounded context ● It’simpossible to build and maintain a model for a large, complex organization: divide et impera ● The preferred way of communication between bounded contexts is using Domain Events via pub/sub
  • 8.
    Ubiquitous language ● Rigourouslanguage, no ambiguity ● It’s the language we use in the code, to name our domain concepts ● Usually valid only inside a bounded context
  • 9.
    Core domain distillation ●DDD is expensive both in analysis and implementation, so it’s important to know where to use it ● Every large domain has various supporting subdomains for every core domain ● Usually found following the money :-)
  • 10.
    Tactical tools ● Entities ●Aggregates ● Value Objects ● Domain services ● Domain events ● Repositories ● Factories (anti corruption layer)
  • 11.
    Entities and Aggregates ●An entity is just a PO(C|J)O object that expresses a domain concept and enforces the domain invariant(s) ● Persistence ignorance ● Holds the business logic of the domain and its state ● Has an identity throughout the bounded context (Identity equality) ● An aggregate is a transaction boundary consisting in several entities held together by an aggregate root
  • 12.
    Value Objects ● Plainsimple records ● Immutable ● Structural equality (no identity)
  • 13.
    Entities vs ValueObjects ● Should this be and Entity or a Value Object? The answer can be subtle or obvious, and depends mostly on the context ● Usually in a 70/30 ratio
  • 14.
    Domain Services ● “Theoperation relates to a domain concept that is not a natural part of an Entity or Value Object” ● First class citizens of the domain ● Stateless
  • 15.
    Domain Events ● “Neldominio è successo qualcosa di interessante per un domain expert” ● Can (asynchronously) cross the boundaries of an aggregate ● Compensating events
  • 16.
    Repositories ● A repositoryis a class whose sole purpose is to collaborate with an entity for data persistence ● SRP is enforced ● Emphasys on the data access pattern, which is made explicit
  • 17.
    Factories/Validators ● Responsibles forcreating the entities ● Anti corruption layer ● The domain has to be always valid, creating entities in invalid state must be impossible ● Usually there is a strong coupling between factories and the entities they create, but that’s ok.
  • 18.
  • 19.
    Testing ● The coredomain has to be unit tested, ideally with a 100% coverage ● I usually test factories and repositories in integration
  • 20.
  • 21.
    CQRS (Command QueryResponsibility Separation)
  • 22.
    DDD + CQ(R)S ●Only way I’ve found to write a reliable, rock solid DOMAIN model ● Domain Entities ○ Enforces invariants ○ Express business model, relationships ○ Have only public methods ○ They’re the write part of the model ● Views ○ Used for queries: ○ Very dumb, no business logic (only a little, if any, of presentation logic) ○ They’re read-only for the domain (i.e.: they come out, never go in) ○ Tailored to the specific user view (there are A LOT of views, but that’s ok)
  • 23.
    How I doit (with a single RDBMS) public interface IDbDto<DTO> { TDto ToDto(); void Load(TDto dto); } - Dtos are the ONLY data saved to and loaded from the database - The interface is hidden until we do a cast (which can only be done in the repository) - The Dtos are used to hydrate (fill the data in) the views and the entities alike Every entity explicitly implements the interface IDbDto
  • 24.
    ● Very dumbclass ● No constructor ● Everything is public ● Usually denormalized ● Read-only for the domain ● Constructor sets the identity ● Class enforces domain invariants ● No public properties (even read-only) ● Public methods only ● State is completely private public class Cart : IDbDto<CartDto> { public Guid Id {get; } public Cart (Customer customer); public Unit AddItem(Item item); public Unit CheckOut(); } public class CartView { public ItemView[] Items {get; set} public string CustomerName {get; set;} public string CustomerAddress {get; set;} public double Amount {get; set;} } public class CartDto { public Guid Id {get; set} public Guid CustomerId {get; set} public ItemDto[] Items; } ● Another dumb class ● Usually Normalized ● No constructor, public ● This is where an ORM may be handy
  • 25.
    Functional DDD ● Really?It’s intrinsically anaemic (Record + Services) ● CQRS (State as application of a series of events) fits better
  • 26.