What is Domain Driven Design (DDD) ?
It is a software development approach used for complex needs, connecting the implementation to an evolving model of the core business concepts. It puts the focus on the problem domain and helps identify the architecture.
Key Benefits of DDD
- Business necessities oriented: Developers communicate better with the business team and the work is more efficient
- A Common set of terms used by entire team: The language is linked to the domain model of the project
- Better Code: more readable and less duplication code
- Agility: clarifies the mental model of domain experts into a useful model for the business
- Keep focus on the solution: clean boundaries around pure models enables the developers to put their efforts on what matters the most. It enables them to focus on the solution
- Ubiquitous Language: Bridges the gap between developers and experts
- Bounded Context: Clear boundaries between different parts of the system
- Core Domain: Focus on the most important part of the system (refer to the existing solutions for not important part of the system)
This is the classical onion architecture, which refers that core part of the onion cannot refer to the upper layers and should be independent. While upper layers are relaying on lower layers (relaying core layer as well). Core elements of the model should act in an isolation from others.
Core part of the Onion would contain: Entities, Value Objects, Domain events and Aggregates. Next upper layer contains: Repositories, Factories and Domain Services. Application Services are located on higher level, and finally most highest layer contains UI.
Separation of Concerns
Core layer elements carry the most important part of the application, its business logic (not all of it of course but most part). Entity and Value Object should do only one thing which is representing a domain objects. They should not contain any knowledge about how they are persisting in the repository. Cleaner we keep our domain model, easier it will be reason about it.
Entity vs Value
To define the differences between entities and value objects, three types of equality should be considered:
- Reference equality means that two objects are deemed to be equal if they reference the same address in the memory
- Identifier equality implies a class has an id field. Two instances of such a class would be equal if they have the same identifiers
- Structurual equality when we consider two objects equal if all of their members match
The concept of identifier equalityrefers to entities, whereas the concept of structural equality - to value objects. In real practice usually value objects don’t have an identifier field and if two avlue objects have the same set of attributes we can treat them interchangeably. if data in two entitiy instances are same (except for the Id property), we don’t consider them as equivalent objects.
Practical Examples for Entity and Value
Entity: if two people have same name you don’t treat them as the same person because of that. Because both of these people have their own inherent identity and specialities.
Value: If a person has a 1 dollar bill, then somehow he exchanged that 1 dollar bill with someone to anothe 1 dollar bill. We don’t care what dollar bill is that, because the value of it doesn’t change. if 1 dollar bill is the same as the other, then why should we bother?
Entities live in a continuum, they have history of what happened to them and how they changed during their lifetime. Value Objects have a zero lifespan. Value objects are created and destroyed with ease.
Value objects should be immutable (the topic of endless discussion). If new value object with different value is needed then its better to destroy the old one and create new one. Entities are almost always mutable!
Modeling Best Practices
Development should be started from implementing Core Domain. Most of the case it is difficult and impossible to implement cored domain without having a data. So that is why most of the time developers try to start from impelementing repository part first to have some data. But It is possible to implement core domain first by using UnitTests. Starting from core domain would help later at repository design part too.