Single Responsibility Principle: Reasons to Change
What This Concept Is
The Single Responsibility Principle (SRP), in Robert Martin's formulation, says:
A class should have one, and only one, reason to change.
The operational word is reason. Responsibility is not a feature, a method, or a line of code. It is a direction from which change pressure arrives: a stakeholder, a policy, or an external system whose evolution can force the class to change.
If two stakeholders can independently demand changes to the same class, that class carries two responsibilities -- and every change risks the other.
Why It Matters Here
SRP is the class-scope specialization of cohesion. A non-cohesive class has multiple responsibilities; those responsibilities correspond to distinct reasons to change, usually aligned with distinct people or systems that care.
Most expensive merge conflicts, surprise regressions, and "why did pricing break when UI changed?" bugs are SRP violations that were never spotted at review time.
Concrete Example
An Employee class with three reasons to change:
class Employee {
BigDecimal calculatePay() { /* HR policy */ }
void save(Connection c) { /* DBA schema */ }
String reportHours() { /* accounting format */ }
}
Three stakeholders: HR, the DBA, and accounting. Three reasons to change. If HR ships a new pay formula, the save method's tests run. If the DBA renames a column, the payroll tests run. Every change is wider than it needs to be.
Apply SRP:
class Employee { /* domain state only */ }
class PayCalculator { BigDecimal calculatePay(Employee e); }
class EmployeeRepository { void save(Employee e, Connection c); }
class HoursReport { String of(Employee e); }
Each class now answers to one stakeholder.
Common Confusion / Misconception
"SRP means a class should only have one method." No. A class can have many methods as long as they serve one reason to change. A Polynomial with twenty methods has one responsibility: polynomial algebra.
A subtler misconception: "SRP means separate what the code does." SRP is about separating why the code changes. Two methods that both implement pricing rules can live together even if one formats a string and the other sums numbers, because they change for the same reason.
A third misconception: "SRP means one class per file." File layout is not the principle. You can have five cohesive, single-responsibility classes in one file.
How To Use It
SRP is easiest to apply by asking questions, not by counting methods:
- Who will demand changes to this class? Name the actual humans or systems.
- If two of those demands arrived at the same time, would both touch the same class?
- If yes, what is the axis of variation they share? If there is no shared axis, split along the axes.
- When you split, the resulting classes should have names ending in
-er,-or,-Service, or a domain noun that answers the "who cares" question.
Check Yourself
- Why does "reasons to change" measure responsibility better than "things the code does"?
- Can a class with one public method still violate SRP? How?
- If two responsibilities always change together, have you actually found two responsibilities?
Mini Drill or Application
Pick a class over 100 lines in a project you know. Do all four:
- List every place in the organization (or every external system) that could demand a change to this class.
- For each item, say which method would change.
- If two distinct sources would change different methods, draw the split line.
- Name the two candidate classes using
-er/-or/-Service/ domain-noun conventions.