“A class should have only one reason to change.”
You’ve heard it. You’ve probably quoted it. Maybe you even tattooed it on your forearm in solid monospaced font. The Single Responsibility Principle (SRP), one of the SOLID five, is a sacred cow in object-oriented design.
But maybe — just maybe — it’s time to ask the heretical question:
Is SRP always worth following?
Let’s dive into why you shouldn't blindly sip the SRP KoolAid.
☁️ The Theory Sounds Lovely
SRP tells us: a class should do one thing, and do it well.
It’s clean. It’s pure. It gives you a warm feeling of architectural correctness. Your classes become lean little specialists. Your future self will thank you.
But theory has a nasty habit of smacking into the chaos of the real world.
🤹♂️ “Responsibility” Is a Vague Word
Let’s get this out of the way: what exactly is a "responsibility"?
In a real-world codebase:
- Is generating and exporting a report one responsibility or two?
- Is parsing and validating user input one thing or two?
- Is managing user authentication and session state too much for one class?
SRP’s core idea hinges on a concept that’s… squishy. Different developers draw the line differently. That makes SRP hard to apply consistently, especially in teams.
🧱 SRP Can Lead to Over-Engineering
Try to rigorously apply SRP and you’ll find yourself drowning in a sea of micro-classes:
ReportFormatter
ReportSaver
ReportMetadataAggregator
ReportFilenameSanitizer
ReportIOManager
You’ve replaced one mildly bloated class with a file system that looks like a Java factory exploded. Reading your code now requires a PhD in class archaeology. Good luck onboarding new developers — or even remembering where anything lives after a week.
Sometimes, it’s better to have one chubby, cohesive class than a scattering of anemic ones.
🛠 YAGNI Says Hello
SRP is often sold as future-proofing. “What if we later need to save the report to the cloud?”
But what if you never do?
You just spent an extra few hours decoupling logic that would’ve been fine living together. In the early phases of a project — when things are changing fast — speed of delivery > architectural purity.
Following SRP too early violates another beloved acronym: YAGNI (You Aren’t Gonna Need It).
🕸️ More SRP, More Glue Code
Ironically, breaking a class apart often means writing more code to stitch things back together.
- More interfaces.
- More dependency injection.
- More orchestration.
- More “managers” and “controllers” and “factories.”
Congratulations: you now have smaller classes... and a complex spider web of dependencies. Decoupling doesn’t always make things simpler — it just moves the complexity somewhere else.
🧠 Pragmatism Beats Purity
This isn't a call to throw out SRP entirely. It’s a reminder to apply it with context.
Use it when:
- Classes are genuinely doing too much.
- Different concerns change at different times.
- You’re building a stable, long-lived system that benefits from clean separation.
Ignore it when:
- You’re prototyping.
- You’re building a small utility or script.
- The abstraction adds more overhead than value.
🏁 In Conclusion
SRP is a powerful principle. But like any tool, it can become a blunt instrument when misused. Don’t idolize it. Don’t follow it religiously. And please — don’t drink the SRP KoolAid thinking it’ll solve all your problems.
Code is not art. It’s not math. It’s a messy conversation with the future — and sometimes the clearest message comes from writing code that’s obvious, even if it bends the rules.
Need help refactoring or deciding if you’re overdoing SRP? Ask yourself: if this class changed, what would actually break? And does it matter?