Wrap Up
SRP in one honest sentence
SRP = one reason to change = one actor / stakeholder. Not "one method." Not "one feature count." Not "the class is short." Robert C. Martin's formulation is about who would request a change: if Finance and HR would both force edits to the same class for different reasons, the class has two responsibilities — even if every method looks related.
A class that does "payroll + tax filing + employee email" has three actors (payroll ops, tax team, HR comms). Splitting along those actor boundaries is the principle. Splitting every private helper into its own file is not.
Why SRP is Important
- Simplifies Maintenance: When a class has a single reason to change, you open one file for one stakeholder request and leave other actors' code alone.
- Encourages Reusability: A module owned by one concern is more reusable than a mixed blob that drags payroll rules into a mailer.
- Makes Code Scalable: Growth adds actors and change reasons; SRP keeps those reasons from colliding in the same type.
- Promotes High Cohesion: Everything in the class moves for the same reason, so the class reads as one idea.
- Supports Low Coupling: Separating by actor reduces accidental dependencies between unrelated change streams.
SRP Takeaways
| Principle | Smell | Fix | When it hurts |
|---|---|---|---|
| Single Responsibility Principle | A class has multiple reasons to change (multiple actors), touches unrelated fields, or needs comments like "this part does X, this part does Y." | Split along actor / reason-to-change boundaries; move cross-cutting concerns to collaborators. One class answers to one stakeholder. | Over-splitting creates navigation friction and ceremony. Not every helper method needs its own class. If two "responsibilities" always change together under the same actor, keep them together. |
When applying SRP hurts
- Micro-classes. Ten one-method types that always edit together are worse than one small cohesive class — you paid indirection for zero isolation.
- Feature-count fretting. "This class has four methods so it violates SRP" is a false smell. Count reasons to change / actors, not methods.
- Wrong axis of split. Splitting by technical layer when the real actors are billing vs auth still forces every feature change across all layers.
Smell → fix, in code
The actor test is easy to state and easy to fudge, so pin it to code. Here is the canonical god class — one type three actors quietly co-own:
// One class, three actors editing it for three unrelated reasons.
class Employee {
double calculatePay() { /* comp rules — changes when Payroll changes policy */ }
void save() { /* SQL/ORM — changes when the Persistence team migrates */ }
String printReport() { /* layout — changes when HR wants a new report format */ }
}
Nothing here looks wrong — the methods are all "about an employee." But they answer to three different stakeholders on three different clocks, so a tax-schema migration and an HR report tweak land in the same file, the same review, the same merge. Split along the actors, not the methods:
class Employee { /* identity + data only — the thing the others operate on */ }
class PayCalculator { double calculate(Employee e); } // owned by Payroll
class EmployeeRepository { void save(Employee e); } // owned by Persistence
class PayrollReport { String render(Employee e); } // owned by HR reporting
The decision you are defending. The named alternative is to keep the single Employee class — one file, everything in one place, nothing to wire together — and for a 50-line admin script that is the correct call: there is only one author and one reason to change, so a split would buy indirection and pay nothing. You split only when the three change reasons genuinely arrive from different people: at that point the merged class stops being convenient and becomes a merge-conflict magnet and a blast-radius risk (a persistence refactor can now break payroll). So the defensible rule is not "always split" — it is split when actors diverge, stay merged when one actor owns all three and they always change together. That judgment, not a method count, is SRP.
SRP → Design Patterns
Several patterns help you keep reasons-to-change separated:
- Facade — Provides a single entry point to a complex subsystem without absorbing the subsystem's responsibilities (the facade does not become every actor).
- Strategy — Extracts a family of algorithms so the context class does not own every variation (and therefore every algorithm-owner's change).
- Decorator — Adds responsibilities to an object without modifying the original class (new actor, new wrapper).
- Command — Encapsulates a request as an object, separating invocation from execution logic.
Follow-Up Drills
- Open a class you wrote recently. List every actor who might request a change in the next six months. If you count more than one, sketch a split along those actors — not along method count.
- Refactor a hypothetical
Employeeclass that calculates pay (payroll), saves to the database (persistence), and prints a report (reporting). What three classes might emerge, and which stakeholder owns each? - Give an example where merging two small classes into one is actually the right move (SRP applied too aggressively: same actor, always co-changing).
- Is "a service class with ten methods" automatically an SRP violation? Defend yes or no using the actor test.
Before You Continue
SRP is the foundation for the other SOLID principles. A class that answers to too many actors cannot easily be closed for modification (OCP), cannot honor a clean substitution contract (LSP), and drags in too many dependencies to invert cleanly (DIP). Make the actor / reason-to-change test automatic before moving to OCP.
The operability fingerprint of an SRP violation
The actor test is abstract; the day-to-day symptoms are concrete. You are looking at an SRP violation when: unrelated tickets keep touching the same "god" class; two teams hit merge conflicts on one file because their change streams collide there; or a util/common package is imported by everything and changes on nearly every release. Each of these is the same underlying fault — more than one actor owns the type. The fix is always the same shape: re-split along the stakeholder change streams so each type answers to exactly one.
🤖 Don't fully get this? Learn it with Claude
Stuck on Wrap Up? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.
Build the mental picture, not memorization.
I just read a lesson on **Wrap Up** (OO & Low-Level Design) and want to truly understand it. Explain Wrap Up from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Socratic — adapts to where you're stuck.
Teach me **Wrap Up** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Active recall exposes what you missed.
Quiz me on **Wrap Up** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Intuition + hook + flashcards for long-term memory.
Help me remember **Wrap Up** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.