advanced
Domain models versus anemic models
Place rules with the data they protect when invariants are central, but keep simple DTOs and records when behavior belongs in services or workflows.
A rich domain model encapsulates business rules with data—`order.cancel()` enforces state transitions. An anemic model is data containers (DTOs/records) with logic in services. Rich models shine when invariants are complex and ubiquitous language maps to methods; anemic fits CRUD, integration-heavy workflows, and simple transport shapes.
DDD tactical patterns use aggregates for consistency boundaries; don't put every rule on every object blindly.
On interviews: refactor an anemic `OrderService` conditional into an `Order` method and say when you would not.
Common pitfalls: fat entities knowing persistence, anemic models with logic duplicated across services, and DTOs leaking into domain layer.
The trade-off is cohesive behavior versus thin layers easier for junior teams and ORM mapping.
Checklist:
- Put rules with the data they protect when central.
- Keep persistence mapping outside rich entities if needed.
- Use DTOs at API boundaries only.