Ubiquitous Modeling: Domain-Driven Design
**Domain-Driven Design (DDD)** is an approach to software development for complex needs by connecting the implementation to an evolving model. It is not about technology, but about creating a shared mental model between domain experts and developers.
I. Strategic Design: The Big Picture
1. Ubiquitous Language
The core of DDD is a single language shared by everyone on the team. If a domain expert says "Revision," the code must say `Revision`, not `Version` or `ChangeLog`. This eliminates the "translation layer" where bugs thrive.
2. Bounded Contexts
In large systems, the same term can mean different things. In the **Content Context**, a "User" is an author; in the **Auth Context**, a "User" is a set of credentials. DDD handles this by defining strict boundaries. Each Bounded Context has its own model and its own database schema.
II. Tactical Design: The Building Blocks
1. Entities vs. Value Objects
* **Entities:** Have a distinct identity that spans time (e.g., a `WikiPage` with a ULID).
* **Value Objects:** Have no identity; they are defined by their attributes (e.g., an `Address` or `Money`). They are immutable. If the attributes change, it's a new Value Object.
2. Aggregate Roots
An **Aggregate** is a cluster of associated objects treated as a single unit for data changes. The **Aggregate Root** is the only gatekeeper to the cluster.
**Concrete Example: The `WikiPage` Aggregate**
A `WikiPage` and its `Frontmatter` are a single aggregate. You cannot modify the frontmatter directly; you must go through the page to ensure invariants (like "Title cannot be empty") are enforced.
```java
public class WikiPage {
private final String id;
private PageMetadata metadata; // Value Object
// Business Logic on the Aggregate Root
public void updateTitle(String newTitle) {
if (newTitle == null || newTitle.isBlank()) {
throw new DomainException("Title is mandatory");
}
this.metadata = metadata.withTitle(newTitle);
}
}
```
III. The Aggregate as a Transaction Boundary
A fundamental rule of DDD: **One transaction per aggregate.**
If you need to update two aggregates simultaneously, you use **Domain Events** and eventual consistency. This keeps the system scalable and prevents long-lived database locks across massive object graphs.
IV. Anti-Corruption Layer (ACL)
When integrating with legacy systems or external APIs, use an **ACL**. This is a translation layer that prevents the messy outside model from leaking into your clean domain model.
---
**See Also:**
- [Hexagonal Architecture](HexagonalArchitecture) — The structural home for the domain model.
- [CQRS Pattern](CqrsPattern) — Separating read models from write (aggregate) models.
- [Event Driven Architecture](EventDrivenArchitecture) — Handling cross-aggregate communication.