LESSON 10.1
God objects and anemic models
Contrast the two extremes of bad object design: monolithic God Objects that do everything, and Anemic Domain Models that do nothing but hold data.
6 min read
Software design often swings between two dangerous anti-pattern extremes:
- The God Object (The Blob): One gigantic class that knows too much and does too much.
- The Anemic Domain Model: The opposite extreme—entities that are empty data structures with getters and setters, while procedural "Manager" or "Service" classes manipulate their raw internals.
Both destroy the primary advantages of object-oriented design: cohesion, encapsulation, and maintainability.
The problem
Anti-Pattern 1: The God Object
// God Object: 3,000 lines touching everything
class AppManager {
renderUI() {}
calculateTax() {}
sendEmail() {}
connectToPostgres() {}
processRefund() {}
}Anti-Pattern 2: The Anemic Model
// Anemic entity: zero logic, zero validation, public mutation
class BankAccount {
balance = 0; // Anybody can set this to -999999!
}
// Procedural service does all the work, breaking encapsulation:
class BankService {
withdraw(account, amount) {
if (account.balance >= amount) {
account.balance -= amount;
The pattern: Rich Domain Model
A Rich Domain Model puts business logic right next to the data it operates on. Entities protect their own invariants. External services coordinate operations, but never bypass the entity's encapsulated rules.
In code
When to use it, and when not to
Use Rich Domain Models when:
- Your application has non-trivial business rules, invariants, and multi-step domain workflows.
- You want to eliminate duplicate validation rules scattered across UI, controllers, and services.
Don't use Rich Domain Models when:
- The system is purely data transformation or passthrough ETL with zero business rules.
- Performing bulk batch insertions into analytical data warehouses.
Where you have already seen it
In Domain-Driven Design (DDD), Martin Fowler coined "Anemic Domain Model" to warn against stripping entities of behavior. Frameworks like EventStore and modern DDD aggregates model entities with rich methods (order.cancel(), order.applyDiscount()).
Related patterns
- Rich Domain Model vs Repository: Repositories persist rich domain aggregates; they do not contain business rules.
- God Object vs Facade: A Facade delegates to focused subsystem classes without holding logic itself. A God Object hoards all state and execution logic.
Try it
Shopping Cart Domain LLD
Refactor an anemic cart model so that item limits, coupon validation, and balance checks are encapsulated within the Cart aggregate.