/Domain-Driven Design
🧩
Domain-Driven Design
Day 2 · Architecture / DDD · 40 min
Entity: Has identity that persists over time. Two entities with same attributes but different IDs are different.
- Example:
Payment— each payment has a unique ID, even if amount/merchant are identical.
- Example:
Money(amount: 100, currency: "EUR")— equality by value, not by reference.
- Example:
Paymentis the aggregate root. ContainsLedgerEntryentities,PaymentStatusvalue object. - Rule: Only modify aggregates through the root. External objects only reference the root.
PaymentRepository.findById(id) → Payment
PaymentRepository.save(payment)
Domain Service: Business logic that doesn't belong to a single entity.
- Example:
SettlementService— orchestrates hold release, on-chain tx, and status update.
- Payments context: Payment, Settlement, Balance
- User context: Profile, KYC, Wallet
- Don't let models leak across boundaries. Use events or DTOs at boundaries.
- "Authorization", "Settlement", "Hold" mean the same thing in code, docs, and conversations.
Key Points
- ▸Payment = Aggregate root with LedgerEntry entities
- ▸Money/PaymentStatus = Value Objects (immutable, equal by value)
- ▸Repository abstracts persistence behind collection-like interface
- ▸SettlementService = Domain Service for cross-entity logic
- ▸Bounded Contexts prevent model leakage between domains
- ▸Ubiquitous Language aligns code terms with business terms