Implementing Domain-Driven Design Patterns
1. Implementing Value Objects
| Trait | Detail |
|---|---|
| Identity | By value |
| Immutability | Required |
| Self-validation | Constructor enforces invariants |
| Side-effect free | Methods return new instances |
Example: Email value object
public record Email(String value) {
public Email {
Objects.requireNonNull(value);
if (!value.matches("^[^@]+@[^@]+\\.[^@]+$")) throw new IllegalArgumentException();
value = value.toLowerCase(Locale.ROOT);
}
}
2. Implementing Entities
| Aspect | Implementation |
|---|---|
| ID type | Strongly typed (e.g., OrderId) |
| equals | By ID only |
| Behavior | Methods enforce invariants |
| Setters | Avoid; use intent methods |
3. Implementing Aggregates
| Rule | Detail |
|---|---|
| Cluster of entities | Treated as unit |
| Single entry | Aggregate root |
| Tx boundary | One aggregate per transaction |
| Cross-aggregate | Reference by ID, not object |
4. Implementing Aggregate Roots
Example: Root enforces invariants
public class Order { // aggregate root
private final OrderId id;
private final List<OrderLine> lines = new ArrayList<>();
public void addLine(ProductId p, int qty) {
if (lines.size() >= 100) throw new IllegalStateException("max 100 lines");
lines.add(new OrderLine(p, qty));
}
public List<OrderLine> lines() { return List.copyOf(lines); }
}
5. Implementing Domain Services
| When | Why |
|---|---|
| Behavior spans aggregates | No natural home |
| Stateless | Pure domain operation |
| Domain language | Named after business concept |
Example: Pricing domain service
public class PricingService {
public Money price(Order o, Customer c, DiscountPolicy p) {
return p.apply(o, c);
}
}
6. Implementing Domain Events
| Trait | Detail |
|---|---|
| Past tense | OrderPlaced, PaymentCaptured |
| Immutable | Record what happened |
| Carry minimal data | IDs + essential context |
| Published by aggregate | Collected and dispatched after commit |
7. Designing Rich Domain Models
8. Understanding Anemic vs Rich Domain Models
| Aspect | Anemic | Rich |
|---|---|---|
| Where logic lives | Services | Entities/aggregates |
| Encapsulation | Weak | Strong |
| Test focus | Service tests | Entity unit tests |
9. Defining Bounded Contexts
| Element | Purpose |
|---|---|
| Boundary | Explicit model scope |
| Ubiquitous language | Within context only |
| Context map | Relations between contexts |
| Integration | ACL, conformist, partner, shared kernel |
10. Modeling Business Rules
| Rule Type | Implementation |
|---|---|
| Invariant | Enforced in constructor / mutator |
| Policy | Strategy injected |
| Specification | Composable predicate |
| Workflow | State machine / saga |
11. Designing Entity Relationships
| Relationship | Modeling |
|---|---|
| Within aggregate | Direct object reference |
| Across aggregates | Reference by ID |
| Bidirectional | Avoid unless required |
| Cardinality | Document explicitly (1:1, 1:N, M:N) |