also known as: Pattern-Oriented Object-Oriented Analysis and Design (OOAD)
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.
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.
Key patterns in Tactic DDD are (@Evans:2003):
The following domain model for Tactic DDD gives an overview of the patterns in it:
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):
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:
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):
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.
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.
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.
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.
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.
Any team member designing and developing
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
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.” ↩