Spend time searching the internet for “What is Domain Driven Design” and you’ll quickly find it’s been defined several different ways. Admittedly most of these definitions are excellent and get the point across. My goal for this article is to give you a quick reference of what I believe to be the most important patterns in the DDD toolkit. In my opinion without these patterns your software is not DDD.
Initially introduced and made popular by programmer Eric Evans in his book, Domain-Driven Design: Tackling Complexity in the Heart of Software, domain-driven design aims to ease the creation of complex applications by connecting the related pieces of the software into an ever-evolving model.
Vaughn Vernon in Domain-Driven Design Distilled explains it as a set of tools that assist you in designing and implementing software that delivers high value, both strategically and tactically.
My definition builds upon Vaughn’s definition. Domain Driven Design is a toolkit of patterns allowing you to build a framework for your business while keeping implementations decoupled through abstraction.
Let’s jump right into what I believe are the most important patterns in DDD.
Aggregates and Entities
The first pattern I want to cover is Aggregates and Entities because they are one of the backbones to Domain Driven Design. First, know aggregates are entities, they’re just the top level entity in a parent-child hierarchy.
Alright now to cut to the chase, entities are the nouns of your domain model and they have unique identity. This identity allows you to execute queries against them in the database, like update, delete and select. Entities usually contain properties describing them. These adjective properties can be simple built-in language types or reference Value Objects or entities. Entities should never contain object references to other aggregates. This breaks transactional boundaries, use reference by identity instead. But it’s OK for aggregates to contain object references to child entities that it owns and manages.
Entities should usually have public methods defined that describe actions in your business’s ubiquitous language. These actions represent an action that the noun can take or an action that alters the nouns state. Entity consumers can mutate the state of your entity by calling these methods. Business rules within the entity action methods are enforce through encapsulation. I strongly advise avoid letting outsiders manipulate your entity state directly. Force them to go through entity methods!
Value Objects are immutable objects that are always valid upon instantiation and do not have identity. My VO usage is usually concretely defining the adjectives of entities (i.e. entity properties) in an immutable way. But I’ll occasionally return a Value Object from a Domain Service or Repository method when it adds value.
The two traits of VOs that distinguish them from Entities is they’re immutable and don’t have identity. Because they don’t have identity they cannot be queried directly and so you can’t mutate the VO record directly. You should always go through the entity to get to the value object. If the value object needs to be changed replace the existing object reference with a new one.
So, Entities are nouns with identity within your domain model and Aggregates are top-level Entities. Let’s revisit one of the rules regarding Entities that I mentioned before.
Entities should never contain object references to other aggregates. This breaks transactional boundaries, use reference by identity instead.
So if Aggregates cannot contain object references to other Aggregates than how do we handle scenarios where one Aggregate action needs to alter another Aggregate? Domain Driven Design has this one figured out and this is where Domain Services come in.
Domain Services are stateless objects that, generally speaking, encapsulate business rules spanning multiple aggregates. These services are also the home for business logic that doesn’t really fit into entities.
The domain service would retrieve the necessary aggregate roots from repositories and then call upon entity action methods to trigger the necessary domain logic. Then, you could save the aggregates back to the database to persist the changes.
If you’re familiar with HTML events in browser applications the Domain Events concept is pretty much the same. When an event occurs in the application we can emit an immutable event descriptor object containing just enough information about the event that allows another module of the application to do something about it.
Every domain event should have a date time of when it was raised and usually will contain one or more entity IDs that can be used later in the application for looking up the subjects of the event.
Aggregate Roots and Entities are mutable nouns with identity in your domain. They usually have adjectives (properties) consisting of primitives, other Entities or Value Objects. Aggregate Roots are the top level nouns in your domain.
Value Objects are immutable (objects) adjectives measuring, describing or quantifying nouns within your domain. They can also be used as a way to pass around immutable domain data.
Domain Services are stateless service objects that house domain business logic that doesn’t fit into the boundary of an Entity and they’re used when application behavior spans multiple Aggregate Roots.
Finally, Domain Events are immutable event descriptors that contain minimal data regarding an application event and enable additional application behavior outside of the process that generated the event.
So that’s Domain Driven Design in a nutshell. Hope this was helpful and not too overwhelming. Thanks for reading!