English version: English
When to Use
- Bounded contexts and integration strategies are ready, and the building blocks within the context need to be designed.
- Need to answer "which objects must change together to maintain consistency".
ddd-model-reviewWhen the report shows "invariant expression rate < 60%", orddd-domain-interactionswhen the report shows "events need to carry another aggregate's private data", re-execute as a backtracking target.
Input Requirements
- Required: event streams and command candidates (from
ddd-discover), context catalog and glossary (fromddd-contexts)。 - Optional: context mapping and failure modes (from
ddd-context-map)。
Process
- Extract Invariants: extract "must always be true" business rules (invariants) from commands and events.
- Cluster Objects: using invariants as the connecting thread, cluster objects into aggregate candidates; identify the aggregate root (the sole external entry point).
- Identify Building Blocks: distinguish entities (have identity, have lifecycle) from value objects (no identity, immutable, compared by value) within an aggregate.
- Define Boundary Rules: externally, only references to the aggregate root are held; cross-aggregate references use IDs; each aggregate is a transaction boundary.
- Re-examine External References: for every "foreign reference" object in the model, ask again—do we ourselves need to manage its lifecycle (creation, modification, termination)? If the answer is yes, it should be promoted to an internal aggregate, rather than keeping only an ID reference. Typical triggers: reference-data-type objects (port catalog, calendar, route catalog) must be listed as aggregates if maintained by us.
- Specification Pattern Identification: when a business rule appears in the predicate form "given X, does X satisfy Y" (e.g.,
isSatisfiedBy(Itinerary)), explicitly extract it as a Specification, rather than stuffing it into an if branch inside a factory or service.
- Command Boundaries: for each aggregate, define the commands it handles, pre-validation, and side effects.
- Cross-Aggregate Consistency: strong consistency within an aggregate; eventual consistency between aggregates—define event-driven / compensation / retry strategies.
- Repository Interface Draft: produce a semantic definition of the repository interface for each aggregate (method names + semantics, without code implementation).
Output
| Artifact | Structural Requirements |
|---|---|
| Aggregate Catalog | Table: aggregate name, aggregate root, contained entities, contained value objects, key invariants, key commands |
| Invariant Table | Table: invariant, triggering command, validation location, behavior on violation |
| Entity and Value Object Inventory | Table: name, type (Entity/VO), owning aggregate, identity strategy/equality definition |
| Transaction Boundary Description | List: default rules, exception conditions, concurrency/locking strategy |
| Cross-Aggregate Consistency Strategy | Table: scenario, triggering event, compensation method, idempotency guarantee, retry strategy |
| Repository Interface Draft | Table: aggregate, method, semantic description, query boundary |
Validation Checklist
- Each aggregate corresponds to at least 1 explicit invariant
- Aggregation boundaries explain transaction boundaries; by default, "1 transaction modifies 1 aggregate"
- Cross-aggregate consistency has event and compensation strategies
- No anti-pattern of "dividing aggregates by foreign keys" (aggregates are not ORM relationship mappings)
- The distinction between entities and value objects has a clear rationale (identity vs value semantics)
- Aggregate size is reasonable: a single aggregate should not contain > 5 entities (if it exceeds this, justification is required)
- For every external reference, the question "is its lifecycle managed by us?" has been answered; those answered yes have been promoted to internal aggregates
- "Predicate-type business rules" have been scanned and the Specification pattern evaluated; those selected have been listed as first-class building blocks
Backtracking triggers
- Invariants span multiple contexts → backtrack to
ddd-contexts(consistency requirements are split by boundaries). - Triggered by
ddd-domain-interactions: an event needs to carry another aggregate's private data, indicating that the aggregate boundary needs adjustment. - Triggered by
ddd-model-review: invariant expression rate < 60% (the aggregate may be a data container rather than a behavioral boundary).
Example
@ddd-aggregates
基于以下上下文定义和事件流,帮我设计 Booking 上下文内的聚合:
- 上下文:Booking(预订全生命周期)
- 核心术语:Booking, TimeSlot, BookingPolicy, CheckIn
- 关键事件:BookingRequested, BookingConfirmed, BookingCancelled, CheckInRecorded
请输出聚合目录、不变量表、实体/值对象清单与事务边界说明。