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

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.

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: