OBEY Domain-Driven Design by Eric Evans
Purpose
This repository follows Domain-Driven Design.
All code generation, modification, and review must optimize for:
- a precise model of the domain
- a shared ubiquitous language
- explicit bounded contexts
- rich domain behavior where complexity exists
- disciplined aggregate design
- protection of invariants
- clear separation between domain model and supporting infrastructure
This file is a binding engineering policy: MUST is binding, SHOULD is a strong default, and MUST NOT is forbidden.
Primary Directive
When uncertain, prefer the option that makes the domain model clearer.
Do not optimize primarily for:
- fewer files
- generic reuse
- CRUD convenience
- object-relational mapping convenience
- delivery-layer convenience
- framework conventions
- short-term speed at the cost of model clarity
The model must serve the business meaning first.
What DDD Means in This Repository
DDD here does not mean:
- adding layers for ceremony
- renaming service classes to sound sophisticated
- wrapping CRUD in verbose abstractions
- creating entities with only fields and setters
- turning every concept into an aggregate
- introducing every DDD pattern everywhere
- overengineering simple subdomains
DDD here does mean:
- building code around business concepts
- expressing rules in domain language
- making context boundaries explicit
- protecting invariants with the model
- modeling identity, value, lifecycle, and consistency deliberately
- translating explicitly across context boundaries
- simplifying aggressively outside the core domain
Knowledge Crunching and Deep Models
Rules (MUST unless marked SHOULD or MUST NOT)
- Treat the model as discovered, not invented from technical structure.
- Before adding abstractions, identify what domain experts would call the concept.
- When requirements are ambiguous, look for missing domain distinctions instead of forcing generic names.
- Let awkward code, contradictory language, and repeated conditionals trigger deeper modeling.
- Update names and boundaries when new domain insight appears.
Required behavior (MUST)
- Ask what business rule, policy, lifecycle, or invariant the code is expressing.
- Prefer a deeper model that clarifies behavior over a shallow model that merely stores data.
- Capture newly discovered concepts in names, tests, APIs, and modules.
- Treat refactoring as part of model discovery, not just code cleanup.
Anti-patterns (MUST NOT)
- Starting from database tables and calling the result the domain model
- Preserving vague names after discovering sharper domain language
- Hiding domain complexity behind
type, status, or metadata fields
- Treating the first model as final
Model-Driven Design
Rules (MUST unless marked SHOULD or MUST NOT)
- The implemented design must reflect the model used in discussion.
- If the model cannot guide code, refine the model or the code until they align.
- Domain objects must represent behavior and meaning, not just persistence state.
- Keep modelers close to implementation. Do not separate analysis from coding so far that the model becomes theoretical.
Required behavior (MUST)
- Make important model concepts visible in classes, functions, modules, tests, and interfaces.
- Prefer executable examples and tests over disconnected documentation.
- Keep diagrams and documents lightweight, current, and tied to code.
- Use explanatory models only to teach or reason; do not confuse them with the implementation model unless they are intended to drive code.
Anti-patterns (MUST NOT)
- A design document that uses different names than the code
- Analysts producing models that developers cannot or do not implement
- Code that follows framework conventions while ignoring the domain model
- Diagrams that become authoritative after the code and domain understanding have changed
Breakthrough and Deeper Insight
Rules (MUST unless marked SHOULD or MUST NOT)
- Expect useful models to change after deeper insight.
- Treat a breakthrough model as a candidate for deliberate refactoring, not as churn.
- When a better model appears, compare its explanatory power against migration cost.
- Preserve working behavior while moving toward the deeper model in safe steps.
Required behavior (MUST)
- Look for concepts that simplify many special cases at once.
- Prefer changes that make future business rules easier to express.
- Use awkwardness, contradictions, and repeated failed attempts as signals that the model is shallow.
- Keep focus on the basics when the model becomes too elaborate.
Anti-patterns (MUST NOT)
- Rejecting a better model only because the current one already works
- Big-bang rewrites when incremental migration is possible
- Elaborate abstractions that do not improve domain insight
Making Implicit Concepts Explicit
Rules (MUST unless marked SHOULD or MUST NOT)
- Listen for domain language that is not represented in code.
- Scrutinize awkward APIs, repeated branches, and contradictory names.
- Read domain references, policies, regulations, and prior art when available.
- Try multiple model shapes before settling on one for complex concepts.
Required behavior (MUST)
- Promote hidden constraints, policies, and processes into explicit domain concepts.
- Name the concept before choosing the implementation form.
- Prefer clear domain objects over anonymous helpers when behavior has business meaning.
Anti-patterns (MUST NOT)
- Burying business rules in comments
- Treating contradictions as edge cases instead of modeling signals
- Keeping vague technical flags after discovering the real concept
Ubiquitous Language
Rules (MUST unless marked SHOULD or MUST NOT)
- Use the exact business terms used by domain experts inside a bounded context.
- One concept must have one name inside a bounded context.
- One name must not mean different concepts inside a bounded context.
- Method names, test names, and modules must use the same vocabulary as the domain.
- Rename code when the domain understanding improves.
Required behavior (MUST)
- Prefer names from the active bounded context; in a shipping model, terms such as
Cargo, Itinerary, Handling Event, and Route Specification should appear directly.
- Prefer operation names that express the domain action, such as changing a cargo destination, adding a handling event, checking allocation, or applying an overbooking policy.
- Avoid technical placeholders when a precise domain term exists.
- Avoid names imported from another bounded context without translation.
Anti-patterns (MUST NOT)
- Using technical names where the business has precise names
- Using synonyms for the same concept in the same context
- Reusing the same term for different meanings because it is convenient
- Keeping bad names because they already exist in the database
Communication Artifacts
Rules (MUST unless marked SHOULD or MUST NOT)
- Documents and diagrams must support the ubiquitous language.
- Written design material must be short enough to stay maintained.
- Executable tests are preferred for rules that can be verified.
- Diagrams should emphasize boundaries, relationships, invariants, and lifecycle over class inventory.
Required behavior (MUST)
- Use examples and scenario tests as living documentation.
- Keep glossary-like explanations close to the bounded context they describe.
- Update documents when terminology or context boundaries change.
Anti-patterns (MUST NOT)
- Long design documents that drift away from code
- Diagrams that show every class but hide the model's meaning
- Documentation that introduces vocabulary not used by code or tests
Scenario Walkthroughs
Rules (MUST unless marked SHOULD or MUST NOT)
- Validate the model by walking through real application scenarios.
- Use scenarios to test whether entities, value objects, aggregates, repositories, and factories collaborate naturally.
- When a scenario feels procedural or awkward, look for missing model concepts or wrong boundaries.
- Revisit aggregate and module boundaries after scenario walkthroughs reveal pressure.
Required behavior (MUST)
- Prefer examples that exercise real business decisions, not only CRUD paths.
- Use scenarios to verify object creation, lifecycle transitions, and cross-context translation.
- Let performance tuning follow model clarity; do not distort the model prematurely for optimization.
Anti-patterns (MUST NOT)
- Designing model elements only in isolation
- Treating scenario code as an afterthought after infrastructure is complete
- Optimizing persistence paths before the model expresses the business correctly
Layered Architecture and Smart UI
Rules (MUST unless marked SHOULD or MUST NOT)
- Keep the domain layer as the place where the model and business rules live.
- Separate presentation, application coordination, domain behavior, and infrastructure when the domain is complex enough to need model-driven design.
- Let application code coordinate tasks without owning domain decisions.
- Keep infrastructure services and framework concerns outside domain objects.
- Use Smart UI only for simple applications where rich domain abstraction, reuse, integration, and deep business rules are not important.
Anti-patterns (MUST NOT)
- UI screens, database tables, or framework annotations defining the domain vocabulary
- UI, application coordination, jobs, or scripts carrying domain rules while domain objects stay passive
- choosing Smart UI when the business behavior needs reuse or abstraction
Bounded Contexts
Rules (MUST unless marked SHOULD or MUST NOT)
- Every substantial domain area must belong to a clearly identified bounded context.
- A model is valid only inside its own bounded context.
- Concepts from another context must not be imported directly as if they were native.
- Translation across contexts must be explicit.
- Shared models across multiple contexts are forbidden unless intentionally governed as a shared kernel.
Required behavior (MUST)
- Keep package, module, or namespace ownership explicit.
- Model
Customer separately in different contexts if meanings differ.
- Prefer context-specific contracts, IDs, published language, or anticorruption layers over shared classes.
Anti-patterns (MUST NOT)
- One giant company-wide domain model
- A
shared/domain package that erases boundaries
- Copying foreign terms into the local model without translation
- Reusing one aggregate type across unrelated contexts
Strategic Design
Core Domain
- Invest the most care in the core domain.
- Protect the core domain from foreign models, vendor schemas, and generic abstractions.
- Keep the core domain expressive even if supporting areas are simpler.
Supporting and Generic Subdomains
- Do not over-model commodity concerns.
- Use simpler models where business complexity is low.
- Save the richest modeling effort for the parts that matter strategically.
Context Mapping
- Integration relationships must be visible in code.
- Ownership of translation must be explicit.
- Upstream and downstream influence must be reflected in adapters and contracts.
Anti-patterns (MUST NOT)
- Spending more design effort on plumbing than on the core domain
- Modeling authentication utilities more richly than the pricing engine
- Allowing a legacy system vocabulary to dominate the core model
Model Integrity Patterns
Continuous Integration Within a Context
- A bounded context must keep one internally consistent model.
- Team members working in the same context must integrate terminology and model changes continuously.
- Conflicting meanings inside one context must be resolved quickly through naming, tests, and refactoring.
Context Relationships
Use context relationship patterns intentionally:
Shared Kernel only for a small, jointly governed model subset.
Customer/Supplier when an upstream team commits to downstream needs.
Conformist only when adopting the upstream model is cheaper than translating it.
Anticorruption Layer when protecting the local model from a foreign or legacy model.
Separate Ways when integration cost is higher than shared capability value.
Open Host Service when a context exposes a stable integration protocol.
Published Language when contexts need a documented exchange language.
Context Transformations
- Move from Separate Ways to Shared Kernel only when the overlap is small, valuable, and worth coordination.
- Move from Shared Kernel to Continuous Integration only when teams are ready to share one model frequently.
- Phase out legacy systems by protecting the new model and replacing responsibilities incrementally through translations.
- Evolve Open Host Service toward Published Language when interchange stability is needed beyond one service.
Required behavior (MUST)
- Make context maps visible in package structure, integration adapters, documentation, or tests.
- Name adapters after the relationship they implement when that improves clarity.
- Keep foreign model terms out of the local core unless deliberately accepted as conformist.
Anti-patterns (MUST NOT)
- Accidental shared kernels with no ownership rules
- Calling every integration an anticorruption layer without translation
- Letting upstream APIs silently define downstream domain language
- Treating context mapping as architecture documentation only, not code structure
Distillation
Core Domain
- Identify the part of the model that creates strategic advantage.
- Put the strongest modeling effort and cleanest design into that core.
- Do not bury the core under generic mechanisms, infrastructure, or broad shared abstractions.
Distillation Patterns
Use these patterns when they clarify priority and investment:
Domain Vision Statement for a short statement of the core model's purpose.
Highlighted Core to mark the most important elements inside a larger model.
Generic Subdomain for commodity capabilities that do not deserve rich custom modeling.
Cohesive Mechanism for technical mechanisms that can be separated from domain policy.
Segregated Core when the core is tangled with supporting concerns.
Abstract Core when related specialized models need a stable conceptual foundation.
Required behavior (MUST)
- Make the core domain easy to find in code.
- Keep supporting and generic subdomains simpler unless their complexity is real.
- Choose refactoring targets based on strategic importance, not just local messiness.
Anti-patterns (MUST NOT)
- Spending equal modeling effort on every subsystem
- Letting technical mechanisms dominate the core model
- Hiding the core behind generic shared packages
- Refactoring peripheral code while the core remains unclear
Large-Scale Structure
Rules (MUST unless marked SHOULD or MUST NOT)
- Large-scale structure should help people understand the system, not freeze it.
- Let structure evolve as the model evolves.
- Use a guiding structure only when it reduces cognitive load across contexts.
- Keep the structure minimally restrictive.
Patterns
Use these patterns deliberately:
Evolving Order when structure must emerge through iterative modeling.
System Metaphor only when it genuinely clarifies the model.
Responsibility Layers when responsibilities naturally stratify across the system.
Knowledge Level when rules or policies must be represented explicitly and changed by configuration or data.
Pluggable Component Framework when variation points are stable and worth formalizing.
Required behavior (MUST)
- Combine bounded contexts, distillation, and large-scale structure into one coherent strategy.
- Revisit structure when it no longer fits the model.
- Prefer communication and self-discipline over heavy structural machinery where possible.
Anti-patterns (MUST NOT)
- A master plan that blocks model learning
- A metaphor that sounds clever but misleads design decisions
- Overly restrictive layers that fight the domain
- Framework architecture masquerading as domain structure
Strategic Decision Making
Rules (MUST unless marked SHOULD or MUST NOT)
- Assess the current model and context map before prescribing a strategic structure.
- Decide who owns strategic design choices explicitly.
- Let application development inform strategy; do not impose strategy detached from implementation feedback.
- Architecture teams must stay customer-focused and model-focused, not framework-focused.
- Strategic decisions must remain revisable as domain understanding changes.
Required behavior (MUST)
- Combine bounded contexts with distillation and large-scale structure when system complexity requires it.
- Make strategy visible enough that teams can coordinate without a rigid master plan.
- Keep technical frameworks subordinate to the domain strategy.
- Treat strategic design as team decision-making, not just diagram production.
Anti-patterns (MUST NOT)
- A top-down master plan that ignores model learning
- Strategy owned by people disconnected from implementation
- Technical architecture decisions presented as domain strategy
- Context maps, core-domain decisions, and large-scale structures that are never revisited
Entities
Use entities when
- identity matters over time
- lifecycle matters
- continuity matters beyond current attributes
- business rules depend on “which one” rather than only “what value”
Rules (MUST unless marked SHOULD or MUST NOT)
- Entities must have explicit identity.
- Entities must protect their own valid state transitions.
- Entities must expose intention-revealing behavior, not arbitrary state changes.
- Entities must not be treated as passive records in behavior-rich domains.
Required behavior (MUST)
- Prefer methods that tell an entity what domain action to perform.
- In a shipping model, express destination changes and handling-event additions as model operations rather than procedural data edits.
- Hide direct state changes behind methods that encode domain meaning.
- Keep identity stable and explicit.
Anti-patterns (MUST NOT)
- Public setters for every field
- Application services manually editing all entity state
- UI or application code deciding which transitions are valid
- Entities used only as persistence shells
Value Objects
Use value objects when
- a concept is defined by attributes rather than identity
- the concept has validation rules
- the concept has behavior
- passing a primitive would hide meaning
Rules (MUST unless marked SHOULD or MUST NOT)
- Value objects must be immutable by default.
- Construction must guarantee validity.
- Equality must be by value, not by identity.
- Validation for the concept should live inside the value object.
- Replace primitive obsession aggressively where the concept matters.
Required behavior (MUST)
- Use value objects for descriptive concepts whose attributes together carry domain meaning.
- Name value objects after the domain concept, not the primitive representation.
- Keep validation and side-effect-free operations for the value near the value itself.
- Replace raw primitives when a named quantity, range, code, measurement, or descriptive whole value matters to the model.
Anti-patterns (MUST NOT)
- Repeating the same value validation across handlers
- Passing raw primitives for named domain quantities, ranges, codes, or measurements
- Passing raw strings for meaningful identifiers
- Letting invalid values exist temporarily without an explicit model for incompleteness
Associations and Modules
Associations
- Model associations only when they support behavior or meaning.
- Prefer simpler, more navigable associations over fully connected object graphs.
- Reduce bidirectional associations unless the domain requires them.
- Reference other aggregates by identity unless direct object traversal is part of an invariant boundary.
Modules
- Modules must communicate domain concepts and bounded context ownership.
- Organize modules around model meaning, not only technical layers.
- Keep related concepts together when they change together.
- Avoid infrastructure-driven packaging that hides the domain.
Required behavior (MUST)
- Use package names that match the ubiquitous language.
- Keep model concepts discoverable from the directory structure.
- Split modules when different concepts evolve independently.
Anti-patterns (MUST NOT)
models, services, utils, and helpers as the dominant structure
- Associations created only because the persistence mechanism supports them
- Object graphs that make aggregate boundaries invisible
- Modules grouped by technical artifact while domain concepts are scattered
Aggregates
Purpose
Aggregates are consistency boundaries, not just object graphs.
Rules (MUST unless marked SHOULD or MUST NOT)
- Design aggregates around invariants that must be consistent immediately.
- Keep aggregates as small as possible.
- All modifications that affect aggregate invariants must go through the aggregate root.
- Reference other aggregates by identity unless stronger consistency is truly required.
- Keep transactional boundaries aligned with invariants; do not expand transactions across aggregates merely for convenience.
Required behavior (MUST)
- Put invariant-protecting methods on the aggregate root.
- Keep internal members encapsulated.
- Handle consistency across aggregate boundaries deliberately when the invariant does not belong inside one aggregate.
- Model transactional boundaries deliberately.
Anti-patterns (MUST NOT)
- Large graph aggregates built for object-relational mapping convenience
- Aggregate roots exposing internal collections for arbitrary external state changes
- Transactions modifying many aggregates because object references make it easy
- Confusing parent-child object structure with aggregate boundaries
Domain Services
Use a domain service only when
- the behavior is domain-significant
- the behavior does not naturally belong on one entity or value object
- the operation still belongs to the ubiquitous language
Rules (MUST unless marked SHOULD or MUST NOT)
- A domain service must express a domain concept, not a technical convenience.
- If behavior clearly belongs to an entity or value object, keep it there.
- Do not move behavior into services merely to keep entities thin.
Required behavior (MUST)
- Domain services should sound like the business.
- Domain services should coordinate domain concepts, not infrastructure details.
Anti-patterns (MUST NOT)
- a single
*Service containing all rules for a model area
- a service containing dozens of unrelated policies
- “Domain services” that are only wrappers for repositories or external technical clients
- Extracting behavior from entities prematurely
Explicit Concepts and Specifications
Rules (MUST unless marked SHOULD or MUST NOT)
- Make implicit constraints explicit in the model.
- Model domain processes as domain objects when the process has business meaning.
- Use specifications for named, combinable business rules that answer whether something satisfies a criterion.
- Keep specifications in domain language, not query language.
Required behavior (MUST)
- Extract repeated conditionals into named domain concepts.
- Prefer named concepts such as route specifications, overbooking policies, or allocation rules over anonymous boolean expressions.
- Keep persistence querying concerns separate from domain specifications unless the project deliberately provides translation.
- Use specifications to clarify policy, validation, selection, and compatibility rules.
Anti-patterns (MUST NOT)
- Complex business conditions duplicated across services
- Boolean flags that hide a named domain rule
- Specifications that are just persistence query builders
- Processes represented only as scripts or transaction handlers when the business treats them as concepts
Repositories
Purpose
Repositories provide access to aggregates as part of the model.
Rules (MUST unless marked SHOULD or MUST NOT)
- Repositories exist for aggregate roots, not for every table.
- Repository interfaces must be defined by the domain or application model that uses them.
- Repositories must return domain objects or domain-oriented results.
- Repository contracts must reflect intent where useful.
- Repositories must not become universal query utilities.
Required behavior (MUST)
- Use repositories to reconstitute and persist aggregates.
- Keep infrastructure mapping hidden behind the repository implementation.
- Prefer focused repository methods over giant generic CRUD interfaces when domain intent matters.
- Keep reconstitution paths separate from normal creation paths when that protects invariants.
- Make client code independent of repository implementation details, while repository implementers understand those details.
- Express query criteria as specifications or model concepts when the criteria are domain rules.
- Return domain objects or collections without exposing database structure.
Anti-patterns (MUST NOT)
- Generic repository abstractions that erase domain meaning
- Returning persistence records directly into the domain
- Putting business rules into repository implementations
- Creating one repository per table with no relation to aggregate design
- Letting relational database design dictate object identity, associations, or aggregate boundaries
Factories
Use factories when
- creation is complex
- construction has business rules
- valid creation requires multiple collaborating values
- the creation itself has domain meaning
Rules (MUST unless marked SHOULD or MUST NOT)
- Factories must create valid objects.
- Factories must encode domain creation rules, not technical object assembly.
- Clients and mappers must not contain business construction logic.
- Choose the factory site where creation ownership fits the model.
- Use constructors directly when creation is simple, intention-revealing, and does not expose complex invariants.
- Treat reconstitution from storage separately from new-object creation.
Anti-patterns (MUST NOT)
- Building invalid objects first and fixing them later
- Letting endpoints stitch together aggregates directly
- Using a factory only to hide a trivial constructor
Application Layer
Purpose
The application layer coordinates application tasks.
It does not replace the domain model.
Rules (MUST unless marked SHOULD or MUST NOT)
- Application services load aggregates, call domain behavior, persist results, and coordinate side effects.
- Application services must not hold core business invariants that belong in the domain.
- Application services must speak the ubiquitous language.
- Application services may coordinate transactions and integration publication, but should not become procedural god classes.
Required behavior (MUST)
- Keep each application operation focused on one application action.
- Let domain objects make domain decisions.
- Keep orchestration distinct from business rules.
Anti-patterns (MUST NOT)
- Application services containing all branching business logic
- Application services manipulating entity internals directly
- Repositories, UI handlers, and application services all implementing overlapping rules
Infrastructure
Rules (MUST unless marked SHOULD or MUST NOT)
- Infrastructure is subordinate to the model.
- Object-relational mappings, serializers, external technical clients, delivery mechanisms, messaging details, caches, and framework types must stay out of the domain model.
- Infrastructure must adapt to the model, not the reverse.
- Persistence shape must not define the domain shape.
Anti-patterns (MUST NOT)
- Naming domain concepts after database tables
- Designing aggregates around lazy loading
- Adding methods to entities only because the persistence mechanism needs them
- Letting transport representations become domain objects
Translation at Boundaries
Rules (MUST unless marked SHOULD or MUST NOT)
- Translation is mandatory at context boundaries.
- Translation is usually mandatory between domain objects and transport or persistence representations.
- Anti-corruption layers must preserve the local model rather than mirror foreign models.
- Foreign terms must not silently invade the local ubiquitous language.
Required behavior (MUST)
- Translate external IDs, statuses, and vocabularies explicitly.
- Map transport representations to local commands or domain inputs.
- Keep persistence models and integration models outside the core domain.
Anti-patterns (MUST NOT)
- Passing external API models deep into the domain
- Reusing one representation as delivery input, persistence record, domain object, and integration message
- Adopting vendor status codes as native domain terminology
Supple Design
Rules (MUST unless marked SHOULD or MUST NOT)
- Design interfaces that reveal intention in domain language.
- Prefer side-effect-free functions for calculations and queries.
- Make assertions and invariants explicit in the model.
- Shape objects around conceptual contours, not arbitrary technical convenience.
- Use standalone classes where a concept can be understood without unnecessary dependencies.
- Favor operations that are closed under meaningful domain types when that improves clarity.
- Use declarative design when it makes rules easier to read, combine, and verify.
- Combine specifications with AND, OR, or NOT only while each component meaning remains readable.
- Use subsumption when one specification or category includes another and that relationship matters.
Required behavior (MUST)
- Name methods after what the business is trying to accomplish.
- Separate commands from queries where side effects would surprise readers.
- Put invariant checks where invalid states enter the model.
- Look for cohesive concepts hidden inside long methods, conditionals, or parameter groups.
- Consider a domain-specific language only when it simplifies real domain expression.
Anti-patterns (MUST NOT)
- Technically named APIs that hide intent
- Methods that both ask a question and mutate domain state
- Invariants expressed only in comments or UI/application validation
- Declarative frameworks that obscure rather than clarify business rules
Analysis and Model Patterns
Analysis Patterns
- Use prior domain modeling knowledge when it fits the current domain.
- Do not force an analysis pattern when local language contradicts it.
- Adapt patterns to the bounded context rather than importing them wholesale.
- Search domain literature, prior art, and established formalisms when the team lacks concepts for a good model.
- Use exploration teams for hard modeling problems only when their findings are tested in code and returned to the main team.
Design Patterns in the Model
Use design patterns only when they express the domain model:
Strategy or Policy for interchangeable domain policies.
Composite for part-whole structures that domain experts recognize.
- Avoid patterns that optimize implementation while hiding model meaning.
Required behavior (MUST)
- Reach for established formalisms when the domain already has mature concepts.
- Make pattern names subordinate to domain names.
- Prefer domain-specific names over generic pattern names in public APIs.
Anti-patterns (MUST NOT)
- Applying design patterns because they are familiar rather than because the model needs them
- Naming domain objects after patterns instead of business concepts
- Importing a reference model without validating it against local domain language
Code Generation Rules
When generating code, always do the following in order.
1. Identify the domain concept first
Before writing code, identify:
- the bounded context
- the domain term
- whether the concept is an entity, value object, aggregate, domain service, repository, factory, or specification
- which invariants matter
Do not start from:
- delivery code
- the persistence model
- the database schema
- the REST shape
unless the task is purely infrastructural.
2. Prefer modeling over generic plumbing
If the domain contains real rules:
- put behavior in the model
- introduce value objects
- define aggregate boundaries
- use domain language in APIs
Do not default to procedural services operating on passive records.
3. Use primitives only when they truly carry no domain meaning
Wrap primitives when meaning, validation, unit semantics, or invariants matter.
4. Protect invariants at the model boundary
Do not rely on UI validation, application validation, or repository validation as the primary protection for business rules.
5. Keep the model persistence-ignorant
Do not shape types or boundaries primarily for object-relational mapping convenience.
6. Keep bounded contexts visible in structure
Prefer feature or context ownership in modules and packages.
Avoid architecture that hides business boundaries behind generic folders.
7. Translate foreign models explicitly
Whenever another context, system, transport layer, or persistence format is involved, create translation rather than leakage.
8. Look for implicit concepts
When conditionals, flags, validation blocks, or repeated calculations express business meaning, extract named concepts such as value objects, policies, specifications, or domain services.
9. Preserve strategic priorities
Give the core domain more modeling care than supporting or generic subdomains. Keep context relationships and distillation choices visible when they affect code.
Review Rules
When reviewing or modifying code, actively look for:
Language problems
- vague technical names replacing business terms
- synonyms for one concept
- one term used with multiple meanings
Model problems
- passive entities
- missing value objects
- invalid construction
- missing invariants
- domain logic spread across delivery handlers, application coordination, or repositories
Boundary problems
- bounded context bleeding
- foreign models leaking inward
- shared “common domain” abstractions destroying language clarity
- missing context relationship strategy
- implicit shared kernels with no governance
Aggregate problems
- oversized aggregates
- aggregate roots exposing internal state changes
- direct object references across aggregates where identity should be used
- transactions spanning many aggregates by default
Service problems
- domain services that are really technical helpers
- god services
- application services replacing the whole domain model
Infrastructure problems
- persistence-first modeling
- transport shapes defining the domain
- persistence rules embedded in business logic
Strategic problems
- core domain hidden behind generic infrastructure
- supporting subdomains over-modeled while core logic remains weak
- no visible distillation or large-scale structure where the system complexity requires one
- context map decisions undocumented in code or tests
Testing Rules
Domain tests first
Prioritize tests for:
- entity invariants
- value object validity
- aggregate behavior
- domain services
- specifications and explicit constraints
- application-layer orchestration
- context translation and anticorruption layers
Rules (MUST unless marked SHOULD or MUST NOT)
- Tests must read in the ubiquitous language.
- Tests must verify allowed and forbidden state transitions.
- Tests must verify that invalid objects cannot be created through supported paths.
- Tests must verify translation behavior where anticorruption layers exist.
- Infrastructure tests must stay separate from domain tests.
- Tests for the core domain should read like executable examples of the model.
- Test context boundaries so translations preserve intended meaning.
- Test that one context does not silently break another context's assumptions.
Anti-patterns (MUST NOT)
- Tests named in transport or delivery vocabulary instead of domain vocabulary
- Tests that verify persistence details instead of domain meaning
- Missing tests for invalid transitions and invariant protection
- Tests that validate generic plumbing while leaving core policy untested
Forbidden Patterns
Do not generate or keep these patterns unless explicitly required and justified.
Passive Domain Model
- entities with fields and setters but no real behavior in a complex domain
- all rules living in application services or UI handlers
Smart UI
- UI or application code making domain decisions
- request handlers enforcing core invariants
Persistence-Driven Design
- aggregate boundaries chosen for persistence convenience
- entities shaped around table structures
- domain types depending on persistence mechanics
Primitive Obsession
- raw strings, ints, decimals, and datetimes everywhere for meaningful concepts
- repeated validation logic for the same primitive concept
Shared Model Everything
- one giant shared domain model across contexts
- common abstractions that erase business distinctions
God Services
- single
*Service classes containing many unrelated policies and workflows
- procedural orchestration replacing domain behavior
Invalid Construction
- partially initialized aggregates
- public state changes that bypass invariants
- allowing impossible states because later code will fix them
Fake DDD
- renaming CRUD layers without changing the model
- adding repositories, factories, and services without real domain need
- over-modeling simple supporting subdomains
Context Map Blindness
- integrations with no explicit relationship strategy
- foreign models imported directly into the local core
- shared code treated as neutral when it actually carries another context's language
Pattern-Driven Obscurity
- design patterns that make the domain language harder to see
- frameworks or DSLs that make simple rules harder to verify
- large-scale structures that prevent model evolution
Refactoring Rules
When changing existing code:
- Recover the ubiquitous language.
- Move business rules into entities, value objects, aggregates, or domain services where appropriate.
- Introduce value objects where primitives hide meaning.
- Redraw aggregate boundaries where invariants are unclear or transactional scope is too large.
- Separate bounded contexts that are currently bleeding together.
- Add translation layers where foreign models leak into the domain.
- Break up god services into focused application services plus richer domain behavior.
- Remove persistence and transport assumptions from the model.
- Extract explicit constraints, specifications, and policies from repeated conditionals.
- Clarify context relationships when integration code is ambiguous.
- Distill the core domain out of supporting mechanisms when strategic logic is buried.
- Preserve behavior while improving the model incrementally.
Do not rewrite everything at once unless explicitly required.
Output Expectations
When asked to implement a feature, default to producing:
- bounded context ownership
- domain terms first
- entities or value objects where justified
- aggregates when invariants require a consistency boundary
- specifications or policies when named rules must be evaluated or combined
- repositories for aggregate persistence
- factories when creation is non-trivial
- application services for orchestration
- explicit tra
…(truncated)
1---2name: book-domain-driven-design-full3description: Domain-Driven Design (Eric Evans) — Full rules — comprehensive mandatory coding standards. Use when asked to apply Domain-Driven Design principles or review code against Domain-Driven Design standards.4license: MIT5---6
7# OBEY Domain-Driven Design by Eric Evans
8
9## Purpose
10
11This repository follows **Domain-Driven Design**.
12All code generation, modification, and review must optimize for:
13- a precise model of the domain
14- a shared ubiquitous language
15- explicit bounded contexts
16- rich domain behavior where complexity exists
17- disciplined aggregate design
18- protection of invariants
19- clear separation between domain model and supporting infrastructure
20
21This file is a binding engineering policy: `MUST` is binding, `SHOULD` is a strong default, and `MUST NOT` is forbidden.
22
23---
24
25## Primary Directive
26
27When uncertain, prefer the option that makes the **domain model clearer**.
28
29Do not optimize primarily for:
30- fewer files
31- generic reuse
32- CRUD convenience
33- object-relational mapping convenience
34- delivery-layer convenience
35- framework conventions
36- short-term speed at the cost of model clarity
37
38The model must serve the business meaning first.
39
40---
41
42## What DDD Means in This Repository
43
44DDD here does **not** mean:
45- adding layers for ceremony
46- renaming service classes to sound sophisticated
47- wrapping CRUD in verbose abstractions
48- creating entities with only fields and setters
49- turning every concept into an aggregate
50- introducing every DDD pattern everywhere
51- overengineering simple subdomains
52
53DDD here **does** mean:
54- building code around business concepts
55- expressing rules in domain language
56- making context boundaries explicit
57- protecting invariants with the model
58- modeling identity, value, lifecycle, and consistency deliberately
59- translating explicitly across context boundaries
60- simplifying aggressively outside the core domain
61
62---
63
64## Knowledge Crunching and Deep Models
65
66### Rules (MUST unless marked SHOULD or MUST NOT)
671. Treat the model as discovered, not invented from technical structure.
682. Before adding abstractions, identify what domain experts would call the concept.
693. When requirements are ambiguous, look for missing domain distinctions instead of forcing generic names.
704. Let awkward code, contradictory language, and repeated conditionals trigger deeper modeling.
715. Update names and boundaries when new domain insight appears.
72
73### Required behavior (MUST)
74- Ask what business rule, policy, lifecycle, or invariant the code is expressing.
75- Prefer a deeper model that clarifies behavior over a shallow model that merely stores data.
76- Capture newly discovered concepts in names, tests, APIs, and modules.
77- Treat refactoring as part of model discovery, not just code cleanup.
78
79### Anti-patterns (MUST NOT)
80- Starting from database tables and calling the result the domain model
81- Preserving vague names after discovering sharper domain language
82- Hiding domain complexity behind `type`, `status`, or `metadata` fields
83- Treating the first model as final
84
85---
86
87## Model-Driven Design
88
89### Rules (MUST unless marked SHOULD or MUST NOT)
901. The implemented design must reflect the model used in discussion.
912. If the model cannot guide code, refine the model or the code until they align.
923. Domain objects must represent behavior and meaning, not just persistence state.
934. Keep modelers close to implementation. Do not separate analysis from coding so far that the model becomes theoretical.
94
95### Required behavior (MUST)
96- Make important model concepts visible in classes, functions, modules, tests, and interfaces.
97- Prefer executable examples and tests over disconnected documentation.
98- Keep diagrams and documents lightweight, current, and tied to code.
99- Use explanatory models only to teach or reason; do not confuse them with the implementation model unless they are intended to drive code.
100
101### Anti-patterns (MUST NOT)
102- A design document that uses different names than the code
103- Analysts producing models that developers cannot or do not implement
104- Code that follows framework conventions while ignoring the domain model
105- Diagrams that become authoritative after the code and domain understanding have changed
106
107---
108
109## Breakthrough and Deeper Insight
110
111### Rules (MUST unless marked SHOULD or MUST NOT)
1121. Expect useful models to change after deeper insight.
1132. Treat a breakthrough model as a candidate for deliberate refactoring, not as churn.
1143. When a better model appears, compare its explanatory power against migration cost.
1154. Preserve working behavior while moving toward the deeper model in safe steps.
116
117### Required behavior (MUST)
118- Look for concepts that simplify many special cases at once.
119- Prefer changes that make future business rules easier to express.
120- Use awkwardness, contradictions, and repeated failed attempts as signals that the model is shallow.
121- Keep focus on the basics when the model becomes too elaborate.
122
123### Anti-patterns (MUST NOT)
124- Rejecting a better model only because the current one already works
125- Big-bang rewrites when incremental migration is possible
126- Elaborate abstractions that do not improve domain insight
127
128---
129
130## Making Implicit Concepts Explicit
131
132### Rules (MUST unless marked SHOULD or MUST NOT)
1331. Listen for domain language that is not represented in code.
1342. Scrutinize awkward APIs, repeated branches, and contradictory names.
1353. Read domain references, policies, regulations, and prior art when available.
1364. Try multiple model shapes before settling on one for complex concepts.
137
138### Required behavior (MUST)
139- Promote hidden constraints, policies, and processes into explicit domain concepts.
140- Name the concept before choosing the implementation form.
141- Prefer clear domain objects over anonymous helpers when behavior has business meaning.
142
143### Anti-patterns (MUST NOT)
144- Burying business rules in comments
145- Treating contradictions as edge cases instead of modeling signals
146- Keeping vague technical flags after discovering the real concept
147
148---
149
150## Ubiquitous Language
151
152### Rules (MUST unless marked SHOULD or MUST NOT)
1531. Use the exact business terms used by domain experts inside a bounded context.
1542. One concept must have one name inside a bounded context.
1553. One name must not mean different concepts inside a bounded context.
1564. Method names, test names, and modules must use the same vocabulary as the domain.
1575. Rename code when the domain understanding improves.
158
159### Required behavior (MUST)
160- Prefer names from the active bounded context; in a shipping model, terms such as `Cargo`, `Itinerary`, `Handling Event`, and `Route Specification` should appear directly.
161- Prefer operation names that express the domain action, such as changing a cargo destination, adding a handling event, checking allocation, or applying an overbooking policy.
162- Avoid technical placeholders when a precise domain term exists.
163- Avoid names imported from another bounded context without translation.
164
165### Anti-patterns (MUST NOT)
166- Using technical names where the business has precise names
167- Using synonyms for the same concept in the same context
168- Reusing the same term for different meanings because it is convenient
169- Keeping bad names because they already exist in the database
170
171---
172
173## Communication Artifacts
174
175### Rules (MUST unless marked SHOULD or MUST NOT)
1761. Documents and diagrams must support the ubiquitous language.
1772. Written design material must be short enough to stay maintained.
1783. Executable tests are preferred for rules that can be verified.
1794. Diagrams should emphasize boundaries, relationships, invariants, and lifecycle over class inventory.
180
181### Required behavior (MUST)
182- Use examples and scenario tests as living documentation.
183- Keep glossary-like explanations close to the bounded context they describe.
184- Update documents when terminology or context boundaries change.
185
186### Anti-patterns (MUST NOT)
187- Long design documents that drift away from code
188- Diagrams that show every class but hide the model's meaning
189- Documentation that introduces vocabulary not used by code or tests
190
191---
192
193## Scenario Walkthroughs
194
195### Rules (MUST unless marked SHOULD or MUST NOT)
1961. Validate the model by walking through real application scenarios.
1972. Use scenarios to test whether entities, value objects, aggregates, repositories, and factories collaborate naturally.
1983. When a scenario feels procedural or awkward, look for missing model concepts or wrong boundaries.
1994. Revisit aggregate and module boundaries after scenario walkthroughs reveal pressure.
200
201### Required behavior (MUST)
202- Prefer examples that exercise real business decisions, not only CRUD paths.
203- Use scenarios to verify object creation, lifecycle transitions, and cross-context translation.
204- Let performance tuning follow model clarity; do not distort the model prematurely for optimization.
205
206### Anti-patterns (MUST NOT)
207- Designing model elements only in isolation
208- Treating scenario code as an afterthought after infrastructure is complete
209- Optimizing persistence paths before the model expresses the business correctly
210
211---
212
213## Layered Architecture and Smart UI
214
215### Rules (MUST unless marked SHOULD or MUST NOT)
2161. Keep the domain layer as the place where the model and business rules live.
2172. Separate presentation, application coordination, domain behavior, and infrastructure when the domain is complex enough to need model-driven design.
2183. Let application code coordinate tasks without owning domain decisions.
2194. Keep infrastructure services and framework concerns outside domain objects.
2205. Use Smart UI only for simple applications where rich domain abstraction, reuse, integration, and deep business rules are not important.
221
222### Anti-patterns (MUST NOT)
223- UI screens, database tables, or framework annotations defining the domain vocabulary
224- UI, application coordination, jobs, or scripts carrying domain rules while domain objects stay passive
225- choosing Smart UI when the business behavior needs reuse or abstraction
226
227---
228
229## Bounded Contexts
230
231### Rules (MUST unless marked SHOULD or MUST NOT)
2321. Every substantial domain area must belong to a clearly identified bounded context.
2332. A model is valid only inside its own bounded context.
2343. Concepts from another context must not be imported directly as if they were native.
2354. Translation across contexts must be explicit.
2365. Shared models across multiple contexts are forbidden unless intentionally governed as a shared kernel.
237
238### Required behavior (MUST)
239- Keep package, module, or namespace ownership explicit.
240- Model `Customer` separately in different contexts if meanings differ.
241- Prefer context-specific contracts, IDs, published language, or anticorruption layers over shared classes.
242
243### Anti-patterns (MUST NOT)
244- One giant company-wide domain model
245- A `shared/domain` package that erases boundaries
246- Copying foreign terms into the local model without translation
247- Reusing one aggregate type across unrelated contexts
248
249---
250
251## Strategic Design
252
253### Core Domain
2541. Invest the most care in the core domain.
2552. Protect the core domain from foreign models, vendor schemas, and generic abstractions.
2563. Keep the core domain expressive even if supporting areas are simpler.
257
258### Supporting and Generic Subdomains
2591. Do not over-model commodity concerns.
2602. Use simpler models where business complexity is low.
2613. Save the richest modeling effort for the parts that matter strategically.
262
263### Context Mapping
2641. Integration relationships must be visible in code.
2652. Ownership of translation must be explicit.
2663. Upstream and downstream influence must be reflected in adapters and contracts.
267
268### Anti-patterns (MUST NOT)
269- Spending more design effort on plumbing than on the core domain
270- Modeling authentication utilities more richly than the pricing engine
271- Allowing a legacy system vocabulary to dominate the core model
272
273---
274
275## Model Integrity Patterns
276
277### Continuous Integration Within a Context
2781. A bounded context must keep one internally consistent model.
2792. Team members working in the same context must integrate terminology and model changes continuously.
2803. Conflicting meanings inside one context must be resolved quickly through naming, tests, and refactoring.
281
282### Context Relationships
283Use context relationship patterns intentionally:
284- `Shared Kernel` only for a small, jointly governed model subset.
285- `Customer/Supplier` when an upstream team commits to downstream needs.
286- `Conformist` only when adopting the upstream model is cheaper than translating it.
287- `Anticorruption Layer` when protecting the local model from a foreign or legacy model.
288- `Separate Ways` when integration cost is higher than shared capability value.
289- `Open Host Service` when a context exposes a stable integration protocol.
290- `Published Language` when contexts need a documented exchange language.
291
292### Context Transformations
2931. Move from Separate Ways to Shared Kernel only when the overlap is small, valuable, and worth coordination.
2942. Move from Shared Kernel to Continuous Integration only when teams are ready to share one model frequently.
2953. Phase out legacy systems by protecting the new model and replacing responsibilities incrementally through translations.
2964. Evolve Open Host Service toward Published Language when interchange stability is needed beyond one service.
297
298### Required behavior (MUST)
299- Make context maps visible in package structure, integration adapters, documentation, or tests.
300- Name adapters after the relationship they implement when that improves clarity.
301- Keep foreign model terms out of the local core unless deliberately accepted as conformist.
302
303### Anti-patterns (MUST NOT)
304- Accidental shared kernels with no ownership rules
305- Calling every integration an anticorruption layer without translation
306- Letting upstream APIs silently define downstream domain language
307- Treating context mapping as architecture documentation only, not code structure
308
309---
310
311## Distillation
312
313### Core Domain
3141. Identify the part of the model that creates strategic advantage.
3152. Put the strongest modeling effort and cleanest design into that core.
3163. Do not bury the core under generic mechanisms, infrastructure, or broad shared abstractions.
317
318### Distillation Patterns
319Use these patterns when they clarify priority and investment:
320- `Domain Vision Statement` for a short statement of the core model's purpose.
321- `Highlighted Core` to mark the most important elements inside a larger model.
322- `Generic Subdomain` for commodity capabilities that do not deserve rich custom modeling.
323- `Cohesive Mechanism` for technical mechanisms that can be separated from domain policy.
324- `Segregated Core` when the core is tangled with supporting concerns.
325- `Abstract Core` when related specialized models need a stable conceptual foundation.
326
327### Required behavior (MUST)
328- Make the core domain easy to find in code.
329- Keep supporting and generic subdomains simpler unless their complexity is real.
330- Choose refactoring targets based on strategic importance, not just local messiness.
331
332### Anti-patterns (MUST NOT)
333- Spending equal modeling effort on every subsystem
334- Letting technical mechanisms dominate the core model
335- Hiding the core behind generic shared packages
336- Refactoring peripheral code while the core remains unclear
337
338---
339
340## Large-Scale Structure
341
342### Rules (MUST unless marked SHOULD or MUST NOT)
3431. Large-scale structure should help people understand the system, not freeze it.
3442. Let structure evolve as the model evolves.
3453. Use a guiding structure only when it reduces cognitive load across contexts.
3464. Keep the structure minimally restrictive.
347
348### Patterns
349Use these patterns deliberately:
350- `Evolving Order` when structure must emerge through iterative modeling.
351- `System Metaphor` only when it genuinely clarifies the model.
352- `Responsibility Layers` when responsibilities naturally stratify across the system.
353- `Knowledge Level` when rules or policies must be represented explicitly and changed by configuration or data.
354- `Pluggable Component Framework` when variation points are stable and worth formalizing.
355
356### Required behavior (MUST)
357- Combine bounded contexts, distillation, and large-scale structure into one coherent strategy.
358- Revisit structure when it no longer fits the model.
359- Prefer communication and self-discipline over heavy structural machinery where possible.
360
361### Anti-patterns (MUST NOT)
362- A master plan that blocks model learning
363- A metaphor that sounds clever but misleads design decisions
364- Overly restrictive layers that fight the domain
365- Framework architecture masquerading as domain structure
366
367---
368
369## Strategic Decision Making
370
371### Rules (MUST unless marked SHOULD or MUST NOT)
3721. Assess the current model and context map before prescribing a strategic structure.
3732. Decide who owns strategic design choices explicitly.
3743. Let application development inform strategy; do not impose strategy detached from implementation feedback.
3754. Architecture teams must stay customer-focused and model-focused, not framework-focused.
3765. Strategic decisions must remain revisable as domain understanding changes.
377
378### Required behavior (MUST)
379- Combine bounded contexts with distillation and large-scale structure when system complexity requires it.
380- Make strategy visible enough that teams can coordinate without a rigid master plan.
381- Keep technical frameworks subordinate to the domain strategy.
382- Treat strategic design as team decision-making, not just diagram production.
383
384### Anti-patterns (MUST NOT)
385- A top-down master plan that ignores model learning
386- Strategy owned by people disconnected from implementation
387- Technical architecture decisions presented as domain strategy
388- Context maps, core-domain decisions, and large-scale structures that are never revisited
389
390---
391
392## Entities
393
394### Use entities when
395- identity matters over time
396- lifecycle matters
397- continuity matters beyond current attributes
398- business rules depend on “which one” rather than only “what value”
399
400### Rules (MUST unless marked SHOULD or MUST NOT)
4011. Entities must have explicit identity.
4022. Entities must protect their own valid state transitions.
4033. Entities must expose intention-revealing behavior, not arbitrary state changes.
4044. Entities must not be treated as passive records in behavior-rich domains.
405
406### Required behavior (MUST)
407- Prefer methods that tell an entity what domain action to perform.
408- In a shipping model, express destination changes and handling-event additions as model operations rather than procedural data edits.
409- Hide direct state changes behind methods that encode domain meaning.
410- Keep identity stable and explicit.
411
412### Anti-patterns (MUST NOT)
413- Public setters for every field
414- Application services manually editing all entity state
415- UI or application code deciding which transitions are valid
416- Entities used only as persistence shells
417
418---
419
420## Value Objects
421
422### Use value objects when
423- a concept is defined by attributes rather than identity
424- the concept has validation rules
425- the concept has behavior
426- passing a primitive would hide meaning
427
428### Rules (MUST unless marked SHOULD or MUST NOT)
4291. Value objects must be immutable by default.
4302. Construction must guarantee validity.
4313. Equality must be by value, not by identity.
4324. Validation for the concept should live inside the value object.
4335. Replace primitive obsession aggressively where the concept matters.
434
435### Required behavior (MUST)
436- Use value objects for descriptive concepts whose attributes together carry domain meaning.
437- Name value objects after the domain concept, not the primitive representation.
438- Keep validation and side-effect-free operations for the value near the value itself.
439- Replace raw primitives when a named quantity, range, code, measurement, or descriptive whole value matters to the model.
440
441### Anti-patterns (MUST NOT)
442- Repeating the same value validation across handlers
443- Passing raw primitives for named domain quantities, ranges, codes, or measurements
444- Passing raw strings for meaningful identifiers
445- Letting invalid values exist temporarily without an explicit model for incompleteness
446
447---
448
449## Associations and Modules
450
451### Associations
4521. Model associations only when they support behavior or meaning.
4532. Prefer simpler, more navigable associations over fully connected object graphs.
4543. Reduce bidirectional associations unless the domain requires them.
4554. Reference other aggregates by identity unless direct object traversal is part of an invariant boundary.
456
457### Modules
4581. Modules must communicate domain concepts and bounded context ownership.
4592. Organize modules around model meaning, not only technical layers.
4603. Keep related concepts together when they change together.
4614. Avoid infrastructure-driven packaging that hides the domain.
462
463### Required behavior (MUST)
464- Use package names that match the ubiquitous language.
465- Keep model concepts discoverable from the directory structure.
466- Split modules when different concepts evolve independently.
467
468### Anti-patterns (MUST NOT)
469- `models`, `services`, `utils`, and `helpers` as the dominant structure
470- Associations created only because the persistence mechanism supports them
471- Object graphs that make aggregate boundaries invisible
472- Modules grouped by technical artifact while domain concepts are scattered
473
474---
475
476## Aggregates
477
478### Purpose
479Aggregates are **consistency boundaries**, not just object graphs.
480
481### Rules (MUST unless marked SHOULD or MUST NOT)
4821. Design aggregates around invariants that must be consistent immediately.
4832. Keep aggregates as small as possible.
4843. All modifications that affect aggregate invariants must go through the aggregate root.
4854. Reference other aggregates by identity unless stronger consistency is truly required.
4865. Keep transactional boundaries aligned with invariants; do not expand transactions across aggregates merely for convenience.
487
488### Required behavior (MUST)
489- Put invariant-protecting methods on the aggregate root.
490- Keep internal members encapsulated.
491- Handle consistency across aggregate boundaries deliberately when the invariant does not belong inside one aggregate.
492- Model transactional boundaries deliberately.
493
494### Anti-patterns (MUST NOT)
495- Large graph aggregates built for object-relational mapping convenience
496- Aggregate roots exposing internal collections for arbitrary external state changes
497- Transactions modifying many aggregates because object references make it easy
498- Confusing parent-child object structure with aggregate boundaries
499
500---
501
502## Domain Services
503
504### Use a domain service only when
505- the behavior is domain-significant
506- the behavior does not naturally belong on one entity or value object
507- the operation still belongs to the ubiquitous language
508
509### Rules (MUST unless marked SHOULD or MUST NOT)
5101. A domain service must express a domain concept, not a technical convenience.
5112. If behavior clearly belongs to an entity or value object, keep it there.
5123. Do not move behavior into services merely to keep entities thin.
513
514### Required behavior (MUST)
515- Domain services should sound like the business.
516- Domain services should coordinate domain concepts, not infrastructure details.
517
518### Anti-patterns (MUST NOT)
519- a single `*Service` containing all rules for a model area
520- a service containing dozens of unrelated policies
521- “Domain services” that are only wrappers for repositories or external technical clients
522- Extracting behavior from entities prematurely
523
524---
525
526## Explicit Concepts and Specifications
527
528### Rules (MUST unless marked SHOULD or MUST NOT)
5291. Make implicit constraints explicit in the model.
5302. Model domain processes as domain objects when the process has business meaning.
5313. Use specifications for named, combinable business rules that answer whether something satisfies a criterion.
5324. Keep specifications in domain language, not query language.
533
534### Required behavior (MUST)
535- Extract repeated conditionals into named domain concepts.
536- Prefer named concepts such as route specifications, overbooking policies, or allocation rules over anonymous boolean expressions.
537- Keep persistence querying concerns separate from domain specifications unless the project deliberately provides translation.
538- Use specifications to clarify policy, validation, selection, and compatibility rules.
539
540### Anti-patterns (MUST NOT)
541- Complex business conditions duplicated across services
542- Boolean flags that hide a named domain rule
543- Specifications that are just persistence query builders
544- Processes represented only as scripts or transaction handlers when the business treats them as concepts
545
546---
547
548## Repositories
549
550### Purpose
551Repositories provide access to aggregates as part of the model.
552
553### Rules (MUST unless marked SHOULD or MUST NOT)
5541. Repositories exist for aggregate roots, not for every table.
5552. Repository interfaces must be defined by the domain or application model that uses them.
5563. Repositories must return domain objects or domain-oriented results.
5574. Repository contracts must reflect intent where useful.
5585. Repositories must not become universal query utilities.
559
560### Required behavior (MUST)
561- Use repositories to reconstitute and persist aggregates.
562- Keep infrastructure mapping hidden behind the repository implementation.
563- Prefer focused repository methods over giant generic CRUD interfaces when domain intent matters.
564- Keep reconstitution paths separate from normal creation paths when that protects invariants.
565- Make client code independent of repository implementation details, while repository implementers understand those details.
566- Express query criteria as specifications or model concepts when the criteria are domain rules.
567- Return domain objects or collections without exposing database structure.
568
569### Anti-patterns (MUST NOT)
570- Generic repository abstractions that erase domain meaning
571- Returning persistence records directly into the domain
572- Putting business rules into repository implementations
573- Creating one repository per table with no relation to aggregate design
574- Letting relational database design dictate object identity, associations, or aggregate boundaries
575
576---
577
578## Factories
579
580### Use factories when
581- creation is complex
582- construction has business rules
583- valid creation requires multiple collaborating values
584- the creation itself has domain meaning
585
586### Rules (MUST unless marked SHOULD or MUST NOT)
5871. Factories must create valid objects.
5882. Factories must encode domain creation rules, not technical object assembly.
5893. Clients and mappers must not contain business construction logic.
5904. Choose the factory site where creation ownership fits the model.
5915. Use constructors directly when creation is simple, intention-revealing, and does not expose complex invariants.
5926. Treat reconstitution from storage separately from new-object creation.
593
594### Anti-patterns (MUST NOT)
595- Building invalid objects first and fixing them later
596- Letting endpoints stitch together aggregates directly
597- Using a factory only to hide a trivial constructor
598
599## Application Layer
600
601### Purpose
602The application layer coordinates application tasks.
603It does not replace the domain model.
604
605### Rules (MUST unless marked SHOULD or MUST NOT)
6061. Application services load aggregates, call domain behavior, persist results, and coordinate side effects.
6072. Application services must not hold core business invariants that belong in the domain.
6083. Application services must speak the ubiquitous language.
6094. Application services may coordinate transactions and integration publication, but should not become procedural god classes.
610
611### Required behavior (MUST)
612- Keep each application operation focused on one application action.
613- Let domain objects make domain decisions.
614- Keep orchestration distinct from business rules.
615
616### Anti-patterns (MUST NOT)
617- Application services containing all branching business logic
618- Application services manipulating entity internals directly
619- Repositories, UI handlers, and application services all implementing overlapping rules
620
621---
622
623## Infrastructure
624
625### Rules (MUST unless marked SHOULD or MUST NOT)
6261. Infrastructure is subordinate to the model.
6272. Object-relational mappings, serializers, external technical clients, delivery mechanisms, messaging details, caches, and framework types must stay out of the domain model.
6283. Infrastructure must adapt to the model, not the reverse.
6294. Persistence shape must not define the domain shape.
630
631### Anti-patterns (MUST NOT)
632- Naming domain concepts after database tables
633- Designing aggregates around lazy loading
634- Adding methods to entities only because the persistence mechanism needs them
635- Letting transport representations become domain objects
636
637---
638
639## Translation at Boundaries
640
641### Rules (MUST unless marked SHOULD or MUST NOT)
6421. Translation is mandatory at context boundaries.
6432. Translation is usually mandatory between domain objects and transport or persistence representations.
6443. Anti-corruption layers must preserve the local model rather than mirror foreign models.
6454. Foreign terms must not silently invade the local ubiquitous language.
646
647### Required behavior (MUST)
648- Translate external IDs, statuses, and vocabularies explicitly.
649- Map transport representations to local commands or domain inputs.
650- Keep persistence models and integration models outside the core domain.
651
652### Anti-patterns (MUST NOT)
653- Passing external API models deep into the domain
654- Reusing one representation as delivery input, persistence record, domain object, and integration message
655- Adopting vendor status codes as native domain terminology
656
657---
658
659## Supple Design
660
661### Rules (MUST unless marked SHOULD or MUST NOT)
6621. Design interfaces that reveal intention in domain language.
6632. Prefer side-effect-free functions for calculations and queries.
6643. Make assertions and invariants explicit in the model.
6654. Shape objects around conceptual contours, not arbitrary technical convenience.
6665. Use standalone classes where a concept can be understood without unnecessary dependencies.
6676. Favor operations that are closed under meaningful domain types when that improves clarity.
6687. Use declarative design when it makes rules easier to read, combine, and verify.
6698. Combine specifications with AND, OR, or NOT only while each component meaning remains readable.
6709. Use subsumption when one specification or category includes another and that relationship matters.
671
672### Required behavior (MUST)
673- Name methods after what the business is trying to accomplish.
674- Separate commands from queries where side effects would surprise readers.
675- Put invariant checks where invalid states enter the model.
676- Look for cohesive concepts hidden inside long methods, conditionals, or parameter groups.
677- Consider a domain-specific language only when it simplifies real domain expression.
678
679### Anti-patterns (MUST NOT)
680- Technically named APIs that hide intent
681- Methods that both ask a question and mutate domain state
682- Invariants expressed only in comments or UI/application validation
683- Declarative frameworks that obscure rather than clarify business rules
684
685---
686
687## Analysis and Model Patterns
688
689### Analysis Patterns
6901. Use prior domain modeling knowledge when it fits the current domain.
6912. Do not force an analysis pattern when local language contradicts it.
6923. Adapt patterns to the bounded context rather than importing them wholesale.
6934. Search domain literature, prior art, and established formalisms when the team lacks concepts for a good model.
6945. Use exploration teams for hard modeling problems only when their findings are tested in code and returned to the main team.
695
696### Design Patterns in the Model
697Use design patterns only when they express the domain model:
698- `Strategy` or `Policy` for interchangeable domain policies.
699- `Composite` for part-whole structures that domain experts recognize.
700- Avoid patterns that optimize implementation while hiding model meaning.
701
702### Required behavior (MUST)
703- Reach for established formalisms when the domain already has mature concepts.
704- Make pattern names subordinate to domain names.
705- Prefer domain-specific names over generic pattern names in public APIs.
706
707### Anti-patterns (MUST NOT)
708- Applying design patterns because they are familiar rather than because the model needs them
709- Naming domain objects after patterns instead of business concepts
710- Importing a reference model without validating it against local domain language
711
712---
713
714## Code Generation Rules
715
716When generating code, always do the following in order.
717
718### 1. Identify the domain concept first
719Before writing code, identify:
720- the bounded context
721- the domain term
722- whether the concept is an entity, value object, aggregate, domain service, repository, factory, or specification
723- which invariants matter
724
725Do not start from:
726- delivery code
727- the persistence model
728- the database schema
729- the REST shape
730unless the task is purely infrastructural.
731
732### 2. Prefer modeling over generic plumbing
733If the domain contains real rules:
734- put behavior in the model
735- introduce value objects
736- define aggregate boundaries
737- use domain language in APIs
738
739Do not default to procedural services operating on passive records.
740
741### 3. Use primitives only when they truly carry no domain meaning
742Wrap primitives when meaning, validation, unit semantics, or invariants matter.
743
744### 4. Protect invariants at the model boundary
745Do not rely on UI validation, application validation, or repository validation as the primary protection for business rules.
746
747### 5. Keep the model persistence-ignorant
748Do not shape types or boundaries primarily for object-relational mapping convenience.
749
750### 6. Keep bounded contexts visible in structure
751Prefer feature or context ownership in modules and packages.
752Avoid architecture that hides business boundaries behind generic folders.
753
754### 7. Translate foreign models explicitly
755Whenever another context, system, transport layer, or persistence format is involved, create translation rather than leakage.
756
757### 8. Look for implicit concepts
758When conditionals, flags, validation blocks, or repeated calculations express business meaning, extract named concepts such as value objects, policies, specifications, or domain services.
759
760### 9. Preserve strategic priorities
761Give the core domain more modeling care than supporting or generic subdomains. Keep context relationships and distillation choices visible when they affect code.
762
763---
764
765## Review Rules
766
767When reviewing or modifying code, actively look for:
768
769### Language problems
770- vague technical names replacing business terms
771- synonyms for one concept
772- one term used with multiple meanings
773
774### Model problems
775- passive entities
776- missing value objects
777- invalid construction
778- missing invariants
779- domain logic spread across delivery handlers, application coordination, or repositories
780
781### Boundary problems
782- bounded context bleeding
783- foreign models leaking inward
784- shared “common domain” abstractions destroying language clarity
785- missing context relationship strategy
786- implicit shared kernels with no governance
787
788### Aggregate problems
789- oversized aggregates
790- aggregate roots exposing internal state changes
791- direct object references across aggregates where identity should be used
792- transactions spanning many aggregates by default
793
794### Service problems
795- domain services that are really technical helpers
796- god services
797- application services replacing the whole domain model
798
799### Infrastructure problems
800- persistence-first modeling
801- transport shapes defining the domain
802- persistence rules embedded in business logic
803
804### Strategic problems
805- core domain hidden behind generic infrastructure
806- supporting subdomains over-modeled while core logic remains weak
807- no visible distillation or large-scale structure where the system complexity requires one
808- context map decisions undocumented in code or tests
809
810---
811
812## Testing Rules
813
814### Domain tests first
815Prioritize tests for:
816- entity invariants
817- value object validity
818- aggregate behavior
819- domain services
820- specifications and explicit constraints
821- application-layer orchestration
822- context translation and anticorruption layers
823
824### Rules (MUST unless marked SHOULD or MUST NOT)
8251. Tests must read in the ubiquitous language.
8262. Tests must verify allowed and forbidden state transitions.
8273. Tests must verify that invalid objects cannot be created through supported paths.
8284. Tests must verify translation behavior where anticorruption layers exist.
8295. Infrastructure tests must stay separate from domain tests.
8306. Tests for the core domain should read like executable examples of the model.
8317. Test context boundaries so translations preserve intended meaning.
8328. Test that one context does not silently break another context's assumptions.
833
834### Anti-patterns (MUST NOT)
835- Tests named in transport or delivery vocabulary instead of domain vocabulary
836- Tests that verify persistence details instead of domain meaning
837- Missing tests for invalid transitions and invariant protection
838- Tests that validate generic plumbing while leaving core policy untested
839
840---
841
842## Forbidden Patterns
843
844Do not generate or keep these patterns unless explicitly required and justified.
845
846### Passive Domain Model
847- entities with fields and setters but no real behavior in a complex domain
848- all rules living in application services or UI handlers
849
850### Smart UI
851- UI or application code making domain decisions
852- request handlers enforcing core invariants
853
854### Persistence-Driven Design
855- aggregate boundaries chosen for persistence convenience
856- entities shaped around table structures
857- domain types depending on persistence mechanics
858
859### Primitive Obsession
860- raw strings, ints, decimals, and datetimes everywhere for meaningful concepts
861- repeated validation logic for the same primitive concept
862
863### Shared Model Everything
864- one giant shared domain model across contexts
865- common abstractions that erase business distinctions
866
867### God Services
868- single `*Service` classes containing many unrelated policies and workflows
869- procedural orchestration replacing domain behavior
870
871### Invalid Construction
872- partially initialized aggregates
873- public state changes that bypass invariants
874- allowing impossible states because later code will fix them
875
876### Fake DDD
877- renaming CRUD layers without changing the model
878- adding repositories, factories, and services without real domain need
879- over-modeling simple supporting subdomains
880
881### Context Map Blindness
882- integrations with no explicit relationship strategy
883- foreign models imported directly into the local core
884- shared code treated as neutral when it actually carries another context's language
885
886### Pattern-Driven Obscurity
887- design patterns that make the domain language harder to see
888- frameworks or DSLs that make simple rules harder to verify
889- large-scale structures that prevent model evolution
890
891---
892
893## Refactoring Rules
894
895When changing existing code:
896
8971. Recover the ubiquitous language.
8982. Move business rules into entities, value objects, aggregates, or domain services where appropriate.
8993. Introduce value objects where primitives hide meaning.
9004. Redraw aggregate boundaries where invariants are unclear or transactional scope is too large.
9015. Separate bounded contexts that are currently bleeding together.
9026. Add translation layers where foreign models leak into the domain.
9037. Break up god services into focused application services plus richer domain behavior.
9048. Remove persistence and transport assumptions from the model.
9059. Extract explicit constraints, specifications, and policies from repeated conditionals.
90610. Clarify context relationships when integration code is ambiguous.
90711. Distill the core domain out of supporting mechanisms when strategic logic is buried.
90812. Preserve behavior while improving the model incrementally.
909
910Do not rewrite everything at once unless explicitly required.
911
912---
913
914## Output Expectations
915
916When asked to implement a feature, default to producing:
917- bounded context ownership
918- domain terms first
919- entities or value objects where justified
920- aggregates when invariants require a consistency boundary
921- specifications or policies when named rules must be evaluated or combined
922- repositories for aggregate persistence
923- factories when creation is non-trivial
924- application services for orchestration
925- explicit tra
926
927…(truncated)