1. Overview

Domain-Driven Design (DDD) is a major software design approach providing principles and patterns to solve the challenges of complex domain models. Its primary focus is on the core of a business domain and its logic. It aims to break a complex model into smaller and more manageable models. Therefore, DDD leads to building a highly decoupled and independent set of services. A microservice is an example of such a service.

There are several building blocks in DDD that translate conceptual models into software design. Aggregates are one of those building blocks.

In this tutorial, we’ll discuss what an Aggregate Root is in DDD.

2. Basic Domain Objects

Before discussing Aggregates, we’ll first discuss two domain objects used within an Aggregate, namely Entities and Value Objects.

2.1. Entities

An Entity is a domain object with a unique identity. We distinguish Entities by using their identities rather than their attributes. For example, a Credit Card object in the banking domain is an Entity since each Credit Card instance has a unique Identification Number (ID). We check whether two Credit Card instances are the same using their IDs, not their limits.

Entities also encapsulate behaviors. The behavior implements the business logic. Behaviors are exposed through operations. These operations may change the state of Entities. Therefore, Entities are mutable.

Entities are also known as Reference Objects.

2.2. Value Objects

A Value Object is another domain object. Unlike an Entity, a Value Object doesn’t have an identity. The importance of a Value Object stems from its value. For example, a Customer object may have an address attribute which might be the instance of an Address object. In this case, the address is a Value Object since it doesn’t describe a Customer instance uniquely. There might be other Customer instances having the same address.

Value Objects are immutable. For example, if a customer moves somewhere else, we don’t change the value of its address attribute but create a new Address instance. Otherwise, changing the address may affect other customers living in the same address.

3. Aggregates and Aggregate Roots

An Aggregate is a collection of Entities and Value Objects. It may also contain other Aggregates. We treat an Aggregate as a single unit.

An Aggregate has a boundary. The objects within the Aggregate Boundary are called inner objects or child objects. In addition to the boundary, an Aggregate also has an Aggregate Root, also known as the Root Entity. The Aggregate Root has a unique identity from the perspective of the domain.

A bank account is a typical example of an Aggregate in the banking domain. We may represent a bank account using an Account object:

Aggregate

Since an Account ID identifies an Account instance uniquely, we can use it as the Aggregate Root. There are other types of objects within this Aggregate. For example, Transactions are Entity objects since each Transaction object has an ID. However, the Balance instance, which holds the amount of the money in the account and the currency, is a Value Object.

3.1. Properties of Aggregate Roots

An Aggregate Root has a global identity while other objects inside the Aggregate Boundary have local unique identities. Therefore, domain objects outside the Aggregate Boundary must use the Aggregate Root to interact with the inner objects. Nothing outside the Aggregate Boundary can have references to the objects within the Aggregate except the Aggregate Root. However, inner objects within an Aggregate can have references to other Aggregate Roots.

An Aggregate Root provides the necessary interfaces to interact with the inner objects. Therefore, these interfaces implement the business logic for operating on the inner objects.

Additionally, since the Aggregate Root is the entry point to interact with an Aggregate, it’s also responsible for the consistency of changes to the inner objects. The consistency rules are known as Invariants in the DDD jargon. For example, we shouldn’t be able to draw an amount of money more than the amount in the bank account.

The Aggregate Root needs to ensure the atomicity of the updates within the Aggregate. For example, if there’s a problem in processing a transaction, the changes applied to the balance during the problematic transaction must be rolled back.

4. Usage Examples in Design Patterns

In this section, we’ll discuss the usage of Aggregates, hence Aggregate Roots, in the two well-known design patterns, Repository and CQRS.

4.1. The Repository Pattern

The Repository Pattern provides an abstraction for persistent objects in a business domain. It has an interface similar to the interface of a collection for retrieving, adding, updating, and deleting domain objects in a persistent storage like a database. However, this interface is more elaborate than a standard Create, Read, Update, and Delete (CRUD) interface by reflecting the needs of the business domain. Since it’s closer to the business domain, we don’t have to deal with the intricate details of using a database.

It’s a common practice to use an Aggregate Root to access the objects in the persistent storage. Connections, tables, and cursors are a few examples of such objects. We don’t use these objects directly but through an Aggregate Root.

4.2. The CQRS Pattern

The Command Query Responsibility Segregation (CQRS) Pattern separates the command and query interfaces of a service in a business domain. Commands generally update information within a system while queries don’t since they read information from the system. Therefore, the model of updating a system may be different than the model of reading information from the system.

Using an Aggregate and an Aggregate Root in the command interface is a natural choice since it provides transactional consistency between the inner objects while updating them.

5. Conclusion

In this article, we discussed what an aggregate root is in DDD.

Firstly, we saw two basic domain objects, Entities and Value Objects. We distinguish an Entity using its identity whereas a Value Object using its attributes.

Then, we learned that an Aggregate groups different Entities and Value Objects logically by binding them to an Aggregate Root. The Aggregate Root has a global identity. Therefore, it encapsulates access to inner objects. We saw that it’s also responsible for checking Invariants, i.e., the consistency of changes in the Aggregate.


原始标题:What Is an Aggregate Root?