Domain Driven Design
It's a design that specifically focus on the domain of our software. Using DDD gives a much more control on the codebase over writing code instead of DDD.
Introduction
A software development approach that helps to model complex software that closely aligns with the business domain according to the business needs. If you are interested in learning more about (DDD) Domain Driven Design in deep check out Eric Even's book “Domain-Driven Design: Tackling Complexity in the Heart of Software“.
Core Concepts of DDD
Entities and Value Objects
Aggregate and Aggregate Roots
Ubiquitous Language
Bounded Context
Domain Services
Domain Events
We will talk about the first two of them in this newsletter! Stay tuned and,
Entities and Value Objects
An entity represents a specific part of a business domain and can be thought of as a model or a table in database terms. It also represents an object that has behaviors according to its use case. An entity is typically identified by a unique identifier (such as a primary key) that distinguishes it across different states.
A value object is an object without an identity, meaning it is defined entirely by its attributes and not by a unique identifier. It becomes part of an entity to provide more context or meaning within that entity. In a multi-threaded environment, value objects are particularly useful because they are immutable, meaning once they are created, they cannot be altered.
But the question is what is the use of Value Object in DDD?
For example, when an order is placed for a product, the price of the product at the time of the order should be captured as a value object, like Money
. Once the Money
the object is created, its value should not change, ensuring consistency even if the product's price changes later. This immutability prevents potential inconsistencies or errors that could arise if, for instance, the price was accidentally modified by another thread or part of the code. By using a value object, you ensure that the price associated with the order remains the same, regardless of any future changes to the product's price.
Example of creating value 👇
Aggregate and Aggregate Roots
An aggregate refers to a collection of related entities that together form a cohesive unit. For example, in a domain model, an Order
and its associated OrderItem
entities are closely related and can be combined to create an aggregate. The Aggregate Root is the primary entity through which the aggregate is accessed and managed; in this case, Order
serves as the Aggregate Root.
Aggregating related entities helps maintain the integrity of the entire business use case by ensuring that operations are performed within a consistent context. It also facilitates loading all relevant entities into memory together, which simplifies operations and enforces business rules across the aggregate.
The main benefit of defining the aggregate is to enforce business rules on the whole cluster of entities and also you can handle the domain events related to the aggregate inside the aggregate. We will talk about the domain events later.
You can also create a separate Aggregate Root class and move validations roles inside it instead of in the Order class to make the Order class much cleaner and then Inherit the Order class from the Aggregate class. For me, I prefer this way but the above is the simplest example to understand the aggregate.
What’s the benefit of using it in the code technically?
Aggregate ensures that related entities are modified consistently, maintaining business rules and integrity.
It centralizes logic and rules within the aggregate root, reducing the risk of errors and simplifying maintenance.
Operations within the aggregate are atomic, meaning all changes are applied together, ensuring data consistency.
However, loading large aggregates and performing operations on them can be expensive and performance issues can occur. We will talk about this in the next blog to address this issue
In the next blog, we will talk about the next two
Ubiquitous Language
Bounded Context