design-practice-repository

Summaries of artifacts, templates, practices, and techniques for agile architecting (DPR-mm) and service design (SDPR-nn).

DPR Git Pages HomeActivities Index

Activity/Technique: Tactic(al) Domain-Driven Design (DDD)

also known as: Pattern-Oriented Object-Oriented Analysis and Design (OOAD)

Context

Domain-Driven Design (DDD) proposes techniques and patterns to deal with the intrinsic complexity in software development, both organizationally and technically. Key DDD themes are business-orientation, domain modeling, and knowledge reuse both on the strategical (i.e., long term, cross-project) and on the tactical (i.e., application, project, product) level.

Goal and Purpose (When to Use and When not to Use)

As a business analyst (domain expert), I want to understand domain concepts driving and underlying requirements so that the emerging design is grounded in actual requirements.

As a domain-driven designer, I want to design software concepts to address and satisfy requirements so that the stakeholder wants and needs are met in an understandable and traceable way.

Tactic (or tactical) DDD can be seen as Object-Oriented Analysis and Design (OOAD) done well, putting emphasis on the business logic in layered architecture and elaborating upon the Domain Model pattern in Martin Fowler’s “Patterns of Enterprise Application Architecture” (@Fowler:2002). The goals of OOAD and Tactic DDD are:

Tip: There is a deliberate difference between analysis (“what are we building?”) and design (“how will we deliver the ‘what’”?), explained in this tutorial. OOA and OOD can and should be performed hand in hand, and DDD supports both OOA and OOD. The transition should be seamless, hence a common set of patterns and notations is used for the incremental and iterative refinement of both analysis and design.

Instructions (Synopsis, Definition)

Key patterns in Tactic DDD are (@Evans:2003):

The following domain model for Tactic DDD gives an overview of the patterns in it:

Tactic DDD Concepts and their Relations

Aggregates are object clusters serving as storage units, preserving consistency invariants (e.g., an order and its items). They have a single Root Entity (also called Aggregate Root) that may link to additional entities. All entities and value objects in an Aggregate are stored in and loaded from the database together.1 Entities have an identity and a life cycle; Value Objects do not and are immutable. Services contain logic that cannot be easily assigned to a single Entity.

The following CRC card outlines the responsibilities and collaborations of Aggregate Roots (i.e., the root entities in an Aggregate):

CRC Card for DDD Aggregate

Aggregates and Business Rules. An Aggregate in DDD is responsible for business rule enforcement across entities (single entity rules can be enforced by entity). But what is a business rule? The term has (at least) two meanings:

  1. Executable part of the business logic (an algorithm) that is not expressed as sequence of statements, but declaratively.
  2. A statement or condition about the domain model, its elements, and their relationships that always has to be true (i.e., be invariant) to preserve data consistency and ensure accuracy of processing. For instance, the sum of all withdrawals is equal to the sum of all payments; the total amount of player salaries on any sports team in the league does not exceed xM USD; all orders point to customers that actually exist in the real world.

The first meaning of the term is not in focus here, but can be modeled as Entity operations and services. The rules in the second meaning (constraint, invariant) can and should be enforced by DDD Aggregates.

Modeling Steps. In tactic DDD, an already existing OOA/OOD Domain Model is refined to call out instances of these patterns; alternatively, the domain-driven design can also be distilled from the functional requirements directly (possibly via Subdomains, another DDD pattern):

  1. Distinguish stateful Entities from immutable, possibly transient Value Objects; expose cross-cutting or supporting code that does not fit into any class in Services (start withing a Transaction Script per user story or use case).
  2. Group output of Step 1 into Aggregates (storage units, object clusters) and let Aggregates communicate state changes via Domain Events. Watch out for entities that share a common life cycle; for instance, an order physically contains order items that have to be deleted when the containing order is deleted. It probably makes little sense to implement such orders and their items in two separate Aggregates.
  3. Add a Repository for each Aggregate (to implement lifecycle management) and add Factories as needed (generally speaking, never apply a pattern just because it exists; there has to be a solid business-level or technical justification for its use).

Modeling Steps From Analysis to Design

Example(s)

The Context Mapper website provides a number of DDD examples. A model of the Cargo example from the original DDD book (@Evans:2003) can be found in its examples repository.

The main Aggregate of the Cargo sample application is shown in the following figure. It comprises a Cargo Entity that aggregates different Value Objects. You might be wondering how Delivery can be a Value Object with that many attributes indicating some kind of lifecycle (various status attributes, current voyage, last event). If we look at the implementation, we can see that it is in fact implemented as an immutable class that creates a new Delivery instance when changes are made.

Example of a DDD Aggregate in Cargo Case Study

Context Mapper, a DSL and tools for strategic and tactic DDD, provides two model transformations that support the transition from user stories (or use cases) to DDD Subdomains and then Bounded Contexts (a Strategic DDD pattern) containing Aggregates, Entities, and Value Objects. An example is walked through here and a comprehensive end-to-end-demo features Tactic DDD and Context Mapper in combination with service domain-specific languages and tools.

Benefits vs. Effort (Expected Benefits, Skill Levels)

According to Martin Fowler in @Fowler:2002, investing in a Domain Model makes sense if the business logic is inherently complex.

We would argue that there hardly is any system that is simple enough not to benefit from domain modeling in general and Tactic DDD in particular.

Hints and Pitfalls to Avoid

Specific to OOAD and DDD, it is a good idea to establish naming conventions, for instance for Aggregates and their Entities. See Hint 6 in Olaf Zimmermann’s “Technical Writing Tips and Tricks” for rationale and additional examples.

Eric Evans establishes the following design heuristics for Aggregates in his DDD Reference:

In “Implementing DDD”, Vaughn Vernon establishes similar rules for Aggregate design (@Vernon:2013):

These recommendations can also be found online in an article series at dddcommunity.org.

Origins and Signs of Use

DDD has been around, in active use on real-world projects, and supported by a community since the first DDD book came out in 2003; it recently became particularly popular in the microservices community as a way to identify service boundaries (via Strategic DDD).

Tactic DDD was introduced in Eric Evans’ book on DDD (@Evans:2003), but featured even more deeply later in “Implementing Domain-Driven Design” by Vaughn Vernon (@Vernon:2013).

Usage of the pattern names and presence of Domain Model, either drawn informally or modeled in a UML tool or DSL, indicate use.

Practices and Techniques (Refinements, Guides)

There is a GitHub organization called “DDD Crew” that features many business analysis-level extensions to DDD practices, for instance a Aggregate Design Canvas template.

More Information

Data Provenance

title: "Design Practice Repository (DPR): Practice/Technique Tactic DDD"
author: Olaf Zimmermann (ZIO)
date: "07, 16, 2021"
copyright: Olaf Zimmermann, 2020-2021 (unless noted otherwise). All rights reserved.
license: Creative Commons Attribution 4.0 International License
  1. In “The Anatomy Of Domain-Driven Design”, Scott Millet and Samuel Knight define Aggregate like this: “A single object graph may closely relate to the real domain, but it does not make for an effective model. Treating the model as a single consistency boundary in a collaborative domain can lead to conflict for changes that are completely unrelated. […] Therefore: Decompose large objects structures into smaller objects groupings called aggregates which are based around invariants (business rules). An aggregate is a unit of consistency ensuring transactional boundaries are set at the right level of granularity to ensure a usable application by avoiding blocking at the database level.”