When DDD Makes Sense
Domain-Driven Design is not for every project. It is for complex domains where the business logic is the hard part, not the technical implementation.
Signs DDD will help:
Signs DDD is overkill:
Ubiquitous Language
The foundation of DDD is shared language. Domain experts and developers use the same terms, and those terms appear directly in the code.
Not OrderProcessor.execute(orderData) - that is technical language. Instead: Order.place(), Order.ship(), Order.cancel(). The code reads like the business speaks.
Building ubiquitous language requires ongoing collaboration. Event storming workshops, domain expert pairing, glossary maintenance. The language evolves as understanding deepens.
Bounded Contexts
A bounded context is a boundary within which a domain model is consistent. The same word can mean different things in different contexts - and that is okay.
"Customer" in Sales is a lead to nurture. "Customer" in Billing is an account to charge. "Customer" in Support is a person with problems. Each context has its own Customer model, optimized for its needs.
Context mapping defines relationships between contexts: shared kernel (shared model), customer-supplier (one depends on another), conformist (one adopts another's model), anti-corruption layer (translation between models).
Aggregates: Consistency Boundaries
An aggregate is a cluster of objects treated as a unit for data changes. The aggregate root is the only entry point - external code cannot directly modify internal objects.
Aggregates enforce business invariants. An Order aggregate ensures line items do not exceed limits, totals are calculated correctly, and state transitions are valid.
Design aggregates small. Large aggregates create contention and complicate transactions. Reference other aggregates by ID, not by object reference.
Domain Events
Domain events capture things that happened that domain experts care about. OrderPlaced, PaymentReceived, ShipmentDispatched.
Events enable loose coupling. The Order context publishes OrderPlaced. The Shipping context subscribes and creates a shipment. Neither knows about the other's internal model.
Events also provide an audit trail and enable event sourcing if you choose that path.
Tactical Patterns
Entities: Objects with identity that persists over time. An Order remains the same Order even as its state changes.
Value Objects: Immutable objects defined by their attributes. Money, Address, DateRange. Two Money objects with the same amount and currency are equal.
Repositories: Abstractions for aggregate persistence. The domain layer does not know about databases.
Domain Services: Operations that do not belong to any single entity. TransferMoney spans two accounts.
Best Practices
Recommended Reading
💬Discussion
No comments yet
Be the first to share your thoughts!
