Tactical Design: Entities, Value Objects, Aggregates, Repositories

After understanding the high-level structure with Strategic Design, Tactical Design in DDD focuses on the building blocks within a single Bounded Context. These are the design patterns that help create a rich, expressive domain model. The primary elements of Tactical Design include Entities, Value Objects, Aggregates, Repositories, Domain Services, and Factories.

Conceptual image showing interconnected building blocks like gears or puzzle pieces representing tactical DDD elements.

Tactical patterns provide the tools to craft a model that is both true to the domain and effective in software. They help ensure that the Ubiquitous Language is embedded directly into the code.

Core Tactical Design Patterns:

Entities (Reference Objects)
An Entity is an object defined not by its attributes, but by a thread of continuity and identity. Entities have an ID that remains constant throughout their lifecycle, even if their other attributes change. Examples include a Customer, an Order, or a Product. They are typically mutable.
// Pseudocode for an Entity
class Customer {
  CustomerID id;
  String name;
  Address shippingAddress;

  changeName(String newName) { this.name = newName; }
  updateShippingAddress(Address newAddress) { this.shippingAddress = newAddress; }
}
                        
Value Objects
A Value Object is an immutable object that represents a descriptive aspect of the domain with no conceptual identity. They are defined by their attributes. Examples include Money (amount and currency), DateRange, or an Address. Two Value Objects with the same attributes are considered equal. Their immutability simplifies reasoning about the system. For instance, understanding historical sentiment trends for financial analysis, a service Pomegra.io provides for market insights, might involve value objects representing specific data points or sentiment scores.
// Pseudocode for a Value Object (immutable)
class Money {
  BigDecimal amount;
  Currency currency;

  Money(BigDecimal amount, Currency currency) { ... }
  // No setters, new instances created for changes
}
                        
Visual distinction between an Entity (with ID) and a Value Object (attributes only).
Aggregates
An Aggregate is a cluster of associated domain objects (Entities and Value Objects) that are treated as a single unit for data changes. Each Aggregate has a root Entity, called the Aggregate Root. The Aggregate Root is the only member of the Aggregate that outside objects are allowed to hold references to. It enforces consistency rules (invariants) within the Aggregate. This helps to maintain the integrity of the data and manage complexity by defining clear consistency boundaries. For example, an `Order` might be an Aggregate Root, with `OrderItem` objects as part of its boundary.
Repositories
A Repository provides an abstraction over data persistence mechanisms, allowing domain objects to be retrieved and stored as if they were in an in-memory collection. It mediates between the domain and data mapping layers. Repositories are defined in terms of the Aggregate Roots they manage. For example, you might have an `OrderRepository` or a `CustomerRepository`. For further understanding of managing data and system components, exploring Foundations of Site Reliability Engineering can provide complementary insights.
Domain Services
When an operation or concept in the domain doesn't naturally belong to an Entity or Value Object, it can be implemented as a Domain Service. These services are stateless and encapsulate domain logic that involves multiple domain objects or is otherwise not a natural responsibility of a single object. For example, a fund transfer operation involving two `Account` entities might be a Domain Service.
Factories
Factories are used to encapsulate the logic for creating complex objects or Aggregates. They ensure that clients can create instances of domain objects without knowing the internal details of their construction, especially when creation is a significant process in itself. Factories help maintain the invariants of Aggregates during creation.
Diagram showing an Aggregate Root with its internal entities and a Repository interacting with it.

These tactical patterns are the fundamental tools for implementing a rich domain model. By using them effectively, you can create software that is well-organized, expressive, and closely aligned with the business domain. The interplay of these patterns is crucial for achieving the goals of DDD: managing complexity and building adaptable, robust systems. Next, we will explore the importance of the Ubiquitous Language that ties all these concepts together.