Single Responsibility Principle
A class should have one reason to change.
The violation
One ReceiptManager doing everything:
class ReceiptManager { // changes when the maths changes,
BigDecimal total() {...} // AND when the layout changes,
String printText() {...} // AND when storage moves to a database.
void saveToFile() {...}
}
Three unrelated stakeholders (pricing rules, receipt design, infrastructure) now edit the same class. Every change risks the other two jobs, tests must set up all three concerns at once, and the class grows without limit.
The fix
Three classes, each with exactly one reason to change:
Receipt– the purchase and its total (changes with pricing rules)ReceiptPrinter– formatting (changes with receipt design)ReceiptRepository– storage (changes with infrastructure)
Benefits
- Isolated change – a receipt redesign cannot break the totals; a storage migration cannot break either.
- Small, focused tests – the maths is tested without touching formatting or storage.
- Composable – the printer works on any receipt regardless of where it’s stored.