Domain Driven Design (DDD)
The Goal: The primary objective is to capture the Domain Expert's Mental Model into the software.
- Code as Communication: The code is a form of documentation. If a developer reads the code, they should understand the business rules without needing to ask the expert.
- Ubiquitous Language: The language used in the code must strictly match the language spoken by domain experts in this specific context.
Focus: Alignment between code and the business mental model.
Strengths: Ubiquitous Language and Strategic Design (Bounded Contexts) for future decomposition.
Weaknesses: Steep learning curve and heavy reliance on Domain Expert availability.
1. Strategic Design & Bounded Contexts (The Environment)
Before coding, you MUST identify the Bounded Context.
- Context Boundaries: A model is valid only within its context. Do not try to create a "Universal Model".
- Polysemy Check: If a term (e.g., "Ticket") means different things in different parts of the system, split them into separate models (e.g.,
SupportTicket vs LotteryTicket) or separate Bounded Contexts.
- Ubiquitous Language: The language used in the code must strictly match the language spoken by domain experts in this specific context.
2. Tactical Steps
It must follow these steps in order:
- Map Ubiquitous Language: Extract business terms and use them for all class and method names. Avoid technical jargon (e.g., use
placeOrder() not saveOrderToDB()).
- Define Invariants: Identify the rules that must always be true for the domain objects.
- Domain-First Generation: Generate the Domain Layer (Aggregates, Entities, VOs) before touching Infrastructure or Application layers.
- Encapsulation Check: Ensure no setter or property allows an object to enter an invalid state.
3. Layered Architecture (Strict Separation)
| Layer |
Responsibility |
Restriction |
| Domain |
Entities, Value Objects, Aggregates, Domain Services, and Repository Interfaces. |
Strictly Forbidden: Importing ORMs (TypeORM/Hibernate) or Web logic. |
| Application |
Use Cases, transaction orchestration, and DTO mapping. |
Strictly Forbidden: Containing business decision logic or state transitions. |
| Infrastructure |
Repository implementations, API adapters, messaging, and DB schemas. |
Technical details must be encapsulated here and hidden from the core. |
4. Structural Comparison: VO vs. Entity vs. Aggregate
To prevent "God Objects" and memory leakage, the agent must strictly distinguish between Local Entities, Aggregate Roots, and Value Objects. Mixing their responsibilities is a High-Severity Architectural Violation.
| Feature |
Value Object (VO) |
Local Entity |
Aggregate Root |
| Identity |
None. Defined by attributes. |
Local. Unique within the Root. |
Global. Unique system-wide. |
| Immutability |
Yes. Always replace, never modify. |
No. State changes over time. |
No. State changes over time. |
| Persistence |
Stored as values of the Parent. |
Part of the Root's document/table. |
Has its own Repository. |
| Validation |
Self-validating on creation. |
Validated by the Root. |
Guarantees all internal rules. |
| Relationship |
Shared by value. |
Owned by one Root. |
References others by ID ONLY. |
5. Implementation Patterns
A. Aggregate Roots
- State Encapsulation: Attributes must be
private or readonly. Direct access to state is discouraged.
- Behavior over Attributes: Methods must name business intentions (e.g.,
confirmPayment() instead of setStatus('PAID')).
- Consistency Boundaries: The Aggregate Root is the transactional boundary. It ensures all internal invariants are satisfied before state changes.
- Atomic Consistency: Only the data that must be consistent in a single transaction should be in the same Aggregate.
- Interaction Rules:
- An Aggregate acts on itself.
- An Aggregate can hold a reference to the ID (Identity) of another Aggregate, but NEVER the object reference itself.
- Eventual Consistency: To update another Aggregate, publish a Domain Event (e.g.,
OrderPlacedEvent) instead of modifying it directly.
B. Local Entities
- State Encapsulation: Attributes must be
private or readonly.
- Behavior over Attributes: Methods must name business intentions.
- Lifecycle: They exist only inside an Aggregate. If the Root is deleted, they are deleted.
- Access: Cannot be retrieved directly via Repository; must be accessed through the Root.
C. Value Objects
- Self-Validation: An "invalid" VO cannot exist. Validation happens in the constructor.
- Immutability: VOs cannot change. Any modification must return a new instance.
- Value Equality: Comparison must be based on internal attributes, not memory reference. Must implement an
equals() method.
- Examples:
Email, Address, SKU, DateRange, Money.
D. Domain Services
- Definition: Used when an operation involves multiple Aggregates or doesn't naturally fit into the responsibility of a single Entity.
- Statelessness: A Domain Service must be stateless. It performs an action and returns a result without maintaining its own internal state.
- Pure Business Logic: It should only contain domain logic. Interaction with DB/API must be via Interfaces defined in the Domain.
E. Repositories
- Roots Only: Strictly create Repositories for Aggregate Roots. Never for Local Entities or VOs.
- Interface in Domain: The repository signature must only use Domain Types.
- Collection Metaphor: The repository should act like an in-memory collection. Use names like
add(), remove(), get(id). Avoid SQL-like names like insert() or update().
F. Factories
- Complex Creation: If creating an Aggregate requires complex assembly, validation of external data, or invariants that involve multiple steps, use a Factory (method or class).
- Separation: Keep the Entity constructor simple; move complex creation logic to the Factory.
G. Specifications (Explicit Rules)
- Complex Rules: When a business rule is a complex boolean logic (e.g., "Is this customer eligible for a refund?"), do not bury it in an
if statement inside a Service or Entity.
- Explicit Class: Create a specific class (e.g.,
RefundEligibilitySpecification) with a method isSatisfiedBy(candidate).
- Reusability: This allows the rule to be tested in isolation and reused for validation or query filtering.
6. Anti-Patterns to Block (Watchlist)
It must flag or refactor if the following are detected:
- Anemic Domain Model: Domain classes that are just property bags (getters/setters only).
- Logic Leakage: Business rules leaking into Controllers, Application Services, or UI.
- God Aggregates: Overly large aggregates attempting to manage unrelated entities.
- Primitive Obsession: Using
string or number for domain concepts like Email or SKU.
7. Post-Generation Quality Gate
1---2name: domain-driven-design3description: Guardian of **Model-Driven Design**. The primary objective is to capture the domain expert's mental model into the software.4---56# Domain Driven Design (DDD)78**The Goal:** The primary objective is to capture the **Domain Expert's Mental Model** into the software.9- **Code as Communication:** The code is a form of documentation. If a developer reads the code, they should understand the business rules without needing to ask the expert.10- **Ubiquitous Language:** The language used in the code must strictly match the language spoken by domain experts *in this specific context*.11**Focus:** Alignment between code and the business mental model.12**Strengths:** Ubiquitous Language and Strategic Design (Bounded Contexts) for future decomposition.13**Weaknesses:** Steep learning curve and heavy reliance on Domain Expert availability.1415---1617## 1. Strategic Design & Bounded Contexts (The Environment)1819Before coding, you MUST identify the **Bounded Context**.20* **Context Boundaries:** A model is valid *only* within its context. Do not try to create a "Universal Model".21* **Polysemy Check:** If a term (e.g., "Ticket") means different things in different parts of the system, split them into separate models (e.g., `SupportTicket` vs `LotteryTicket`) or separate Bounded Contexts.22* **Ubiquitous Language:** The language used in the code must strictly match the language spoken by domain experts *in this specific context*.2324---2526## 2. Tactical Steps2728It must follow these steps in order:291. **Map Ubiquitous Language:** Extract business terms and use them for all class and method names. Avoid technical jargon (e.g., use `placeOrder()` not `saveOrderToDB()`).302. **Define Invariants:** Identify the rules that must *always* be true for the domain objects.313. **Domain-First Generation:** Generate the **Domain Layer** (Aggregates, Entities, VOs) before touching Infrastructure or Application layers.324. **Encapsulation Check:** Ensure no setter or property allows an object to enter an invalid state.3334---3536## 3. Layered Architecture (Strict Separation)3738| Layer | Responsibility | Restriction |39| :--- | :--- | :--- |40| **Domain** | Entities, Value Objects, Aggregates, Domain Services, and Repository Interfaces. | **Strictly Forbidden:** Importing ORMs (TypeORM/Hibernate) or Web logic. |41| **Application** | Use Cases, transaction orchestration, and DTO mapping. | **Strictly Forbidden:** Containing business decision logic or state transitions. |42| **Infrastructure** | Repository implementations, API adapters, messaging, and DB schemas. | Technical details must be encapsulated here and hidden from the core. |4344---4546## 4. Structural Comparison: VO vs. Entity vs. Aggregate4748To prevent "God Objects" and memory leakage, the agent must strictly distinguish between **Local Entities**, **Aggregate Roots**, and **Value Objects**. Mixing their responsibilities is a **High-Severity Architectural Violation**.4950| Feature | **Value Object (VO)** | **Local Entity** | **Aggregate Root** |51| :--- | :--- | :--- | :--- |52| **Identity** | None. Defined by attributes. | Local. Unique within the Root. | **Global**. Unique system-wide. |53| **Immutability** | **Yes**. Always replace, never modify. | No. State changes over time. | No. State changes over time. |54| **Persistence** | Stored as values of the Parent. | Part of the Root's document/table. | Has its own **Repository**. |55| **Validation** | Self-validating on creation. | Validated by the Root. | Guarantees all internal rules. |56| **Relationship** | Shared by value. | Owned by one Root. | References others by **ID ONLY**. |5758---5960## 5. Implementation Patterns6162#### A. Aggregate Roots63* **State Encapsulation:** Attributes must be `private` or `readonly`. Direct access to state is discouraged.64* **Behavior over Attributes:** Methods must name business intentions (e.g., `confirmPayment()` instead of `setStatus('PAID')`).65* **Consistency Boundaries:** The Aggregate Root is the transactional boundary. It ensures all internal invariants are satisfied before state changes.66* **Atomic Consistency:** Only the data that *must* be consistent in a single transaction should be in the same Aggregate.67* **Interaction Rules:**68 1. An Aggregate acts on itself.69 2. An Aggregate can hold a reference to the **ID** (Identity) of another Aggregate, but **NEVER** the object reference itself.70 3. **Eventual Consistency:** To update another Aggregate, publish a **Domain Event** (e.g., `OrderPlacedEvent`) instead of modifying it directly.7172#### B. Local Entities73* **State Encapsulation:** Attributes must be `private` or `readonly`.74* **Behavior over Attributes:** Methods must name business intentions.75* **Lifecycle:** They exist only inside an Aggregate. If the Root is deleted, they are deleted.76* **Access:** Cannot be retrieved directly via Repository; must be accessed through the Root.7778#### C. Value Objects79* **Self-Validation:** An "invalid" VO cannot exist. Validation happens in the constructor.80* **Immutability:** VOs cannot change. Any modification must return a new instance.81* **Value Equality:** Comparison must be based on internal attributes, not memory reference. Must implement an `equals()` method.82* **Examples:** `Email`, `Address`, `SKU`, `DateRange`, `Money`.8384#### D. Domain Services85* **Definition:** Used when an operation involves multiple Aggregates or doesn't naturally fit into the responsibility of a single Entity.86* **Statelessness:** A Domain Service must be stateless. It performs an action and returns a result without maintaining its own internal state.87* **Pure Business Logic:** It should only contain domain logic. Interaction with DB/API must be via Interfaces defined in the Domain.8889#### E. Repositories90* **Roots Only:** Strictly create Repositories for Aggregate Roots. **Never** for Local Entities or VOs.91* **Interface in Domain:** The repository signature must only use Domain Types.92* **Collection Metaphor:** The repository should act like an in-memory collection. Use names like `add()`, `remove()`, `get(id)`. Avoid SQL-like names like `insert()` or `update()`.9394#### F. Factories95* **Complex Creation:** If creating an Aggregate requires complex assembly, validation of external data, or invariants that involve multiple steps, use a **Factory** (method or class).96* **Separation:** Keep the Entity constructor simple; move complex creation logic to the Factory.9798#### G. Specifications (Explicit Rules)99* **Complex Rules:** When a business rule is a complex boolean logic (e.g., "Is this customer eligible for a refund?"), do not bury it in an `if` statement inside a Service or Entity.100* **Explicit Class:** Create a specific class (e.g., `RefundEligibilitySpecification`) with a method `isSatisfiedBy(candidate)`.101* **Reusability:** This allows the rule to be tested in isolation and reused for validation or query filtering.102103---104105## 6. Anti-Patterns to Block (Watchlist)106107It must **flag** or **refactor** if the following are detected:1081. **Anemic Domain Model:** Domain classes that are just property bags (getters/setters only).1092. **Logic Leakage:** Business rules leaking into Controllers, Application Services, or UI.1103. **God Aggregates:** Overly large aggregates attempting to manage unrelated entities.1114. **Primitive Obsession:** Using `string` or `number` for domain concepts like `Email` or `SKU`.112113---114115## 7. Post-Generation Quality Gate116- [ ] Is the model rich or just a data structure (anemic)?117- [ ] Are Value Objects used to describe entity properties?118- [ ] Does the Domain logic work without any external library/DB dependency?119- [ ] Is persistence logic leaking into the domain?120- [ ] Does the method name describe a business intention (e.g., `enrollStudent` vs `updateStatus`)?121- [ ] Do method names sound like business actions (Ubiquitous Language)?122- [ ] Is the Domain Service stateless and focused only on orchestration?123- [ ] Are all state transitions protected by internal business rules?124- [ ] Are all Value Objects immutable and self-validating?