264 lines
4.2 KiB
Markdown
264 lines
4.2 KiB
Markdown
Domain Objects Design Guide (Clean Architecture)
|
|
|
|
This document defines all domain object types used in the Core and assigns strict responsibilities and boundaries.
|
|
|
|
Its goal is to remove ambiguity between:
|
|
• Entities
|
|
• Value Objects
|
|
• Aggregate Roots
|
|
• Domain Services
|
|
• Domain Events
|
|
|
|
The rules in this document are non-negotiable.
|
|
|
|
⸻
|
|
|
|
Core Principle
|
|
|
|
Domain objects represent business truth.
|
|
|
|
They:
|
|
• outlive APIs and UIs
|
|
• must remain stable over time
|
|
• must not depend on technical details
|
|
|
|
If a class answers a business question, it belongs here.
|
|
|
|
⸻
|
|
|
|
1. Entities
|
|
|
|
Definition
|
|
|
|
An Entity is a domain object that:
|
|
• has a stable identity
|
|
• changes over time
|
|
• represents a business concept
|
|
|
|
Identity matters more than attributes.
|
|
|
|
⸻
|
|
|
|
Responsibilities
|
|
|
|
Entities MUST:
|
|
• own their identity
|
|
• enforce invariants on state changes
|
|
• expose behavior, not setters
|
|
|
|
Entities MUST NOT:
|
|
• depend on DTOs or transport models
|
|
• access repositories or services
|
|
• perform IO
|
|
• know about frameworks
|
|
|
|
⸻
|
|
|
|
Creation Rules
|
|
• New entities are created via create()
|
|
• Existing entities are reconstructed via rehydrate()
|
|
|
|
core/<context>/domain/entities/
|
|
|
|
|
|
⸻
|
|
|
|
Example
|
|
• League
|
|
• Season
|
|
• Race
|
|
• Driver
|
|
|
|
⸻
|
|
|
|
2. Value Objects
|
|
|
|
Definition
|
|
|
|
A Value Object is a domain object that:
|
|
• has no identity
|
|
• is immutable
|
|
• is defined by its value
|
|
|
|
⸻
|
|
|
|
Responsibilities
|
|
|
|
Value Objects MUST:
|
|
• validate their own invariants
|
|
• be immutable
|
|
• be comparable by value
|
|
|
|
Value Objects MUST NOT:
|
|
• contain business workflows
|
|
• reference entities
|
|
• perform IO
|
|
|
|
⸻
|
|
|
|
Creation Rules
|
|
• create() for new domain meaning
|
|
• fromX() for interpreting external formats
|
|
|
|
core/<context>/domain/value-objects/
|
|
|
|
|
|
⸻
|
|
|
|
Example
|
|
• Money
|
|
• LeagueName
|
|
• RaceTimeOfDay
|
|
• SeasonSchedule
|
|
|
|
⸻
|
|
|
|
3. Aggregate Roots
|
|
|
|
Definition
|
|
|
|
An Aggregate Root is an entity that:
|
|
• acts as the consistency boundary
|
|
• protects invariants across related entities
|
|
|
|
All access to the aggregate happens through the root.
|
|
|
|
⸻
|
|
|
|
Responsibilities
|
|
|
|
Aggregate Roots MUST:
|
|
• enforce consistency rules
|
|
• control modifications of child entities
|
|
|
|
Aggregate Roots MUST NOT:
|
|
• expose internal collections directly
|
|
• allow partial updates bypassing rules
|
|
|
|
⸻
|
|
|
|
Example
|
|
• League (root)
|
|
• Season (root)
|
|
|
|
⸻
|
|
|
|
4. Domain Services
|
|
|
|
Definition
|
|
|
|
A Domain Service encapsulates domain logic that:
|
|
• does not naturally belong to a single entity
|
|
• involves multiple domain objects
|
|
|
|
⸻
|
|
|
|
Responsibilities
|
|
|
|
Domain Services MAY:
|
|
• coordinate entities
|
|
• calculate derived domain values
|
|
|
|
Domain Services MUST:
|
|
• operate only on domain types
|
|
• remain stateless
|
|
|
|
Domain Services MUST NOT:
|
|
• access repositories
|
|
• orchestrate use cases
|
|
• perform IO
|
|
|
|
core/<context>/domain/services/
|
|
|
|
|
|
⸻
|
|
|
|
Example
|
|
• SeasonConfigurationFactory
|
|
• ChampionshipAggregator
|
|
• StrengthOfFieldCalculator
|
|
|
|
⸻
|
|
|
|
5. Domain Events
|
|
|
|
Definition
|
|
|
|
A Domain Event represents something that:
|
|
• has already happened
|
|
• is important to the business
|
|
|
|
⸻
|
|
|
|
Responsibilities
|
|
|
|
Domain Events MUST:
|
|
• be immutable
|
|
• carry minimal information
|
|
|
|
Domain Events MUST NOT:
|
|
• contain behavior
|
|
• perform side effects
|
|
|
|
core/<context>/domain/events/
|
|
|
|
|
|
⸻
|
|
|
|
Example
|
|
• RaceCompleted
|
|
• SeasonActivated
|
|
|
|
⸻
|
|
|
|
6. What Does NOT Belong in Domain Objects
|
|
|
|
❌ DTOs
|
|
❌ API Models
|
|
❌ View Models
|
|
❌ Repositories
|
|
❌ Framework Types
|
|
❌ Logging
|
|
❌ Configuration
|
|
|
|
If it depends on infrastructure, it does not belong here.
|
|
|
|
⸻
|
|
|
|
7. Dependency Rules
|
|
|
|
Entities → Value Objects
|
|
Entities → Domain Services
|
|
Domain Services → Entities
|
|
|
|
Reverse dependencies are forbidden.
|
|
|
|
⸻
|
|
|
|
8. Testing Requirements
|
|
|
|
Domain Objects MUST:
|
|
• have unit tests for invariants
|
|
• be tested without mocks
|
|
|
|
Domain Services MUST:
|
|
• have deterministic tests
|
|
|
|
⸻
|
|
|
|
Mental Model (Final)
|
|
|
|
Entities protect state.
|
|
Value Objects protect meaning.
|
|
Aggregate Roots protect consistency.
|
|
Domain Services protect cross-entity rules.
|
|
Domain Events describe facts.
|
|
|
|
⸻
|
|
|
|
Final Summary
|
|
• Domain objects represent business truth
|
|
• They are pure and framework-free
|
|
• They form the most stable part of the system
|
|
|
|
If domain objects are clean, everything else becomes easier. |