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.