The single responsibility principle says a class, function, or module should have exactly one reason to change. It is the first letter in SOLID and, in practice, the most frequently violated of the five, because responsibilities creep in gradually rather than arriving all at once. A class that starts out doing one job quietly picks up a second and third over a few sprints, and nobody notices until a change in one area breaks something unrelated.
What changed in 2026
- AI-generated code tends to extend existing classes rather than create new ones. Sticking new logic into a file that is already open is the path of least resistance for a model completing a diff, so single responsibility violations show up more often in AI-assisted pull requests unless reviewed for scope.
- Coupling metrics are now a normal CI check. Static analysis that flags classes with too many collaborators or too many reasons to change has moved from academic tooling into everyday linting.
- The microservices retrospective landed. After a decade of splitting systems into services, the 2026 consensus is that single responsibility still has to be applied inside each service, at the function and class level; splitting services without splitting responsibilities just moves the mess.
What one reason to change actually means
Robert C. Martin later clarified the principle with an actor-based definition: a reason to change is tied to a single actor or stakeholder, not a literal count of tasks. A class with three methods can still have a single responsibility if all three exist to serve the same stakeholder and always change together. The common misreading, that a class should have exactly one method, is not what the principle says.
A concrete example
// Before: three reasons to change live in one class
class Invoice {
calculateTotal() { /* ... */ }
formatAsHtml() { /* ... */ }
saveToDatabase() { /* ... */ }
}
// After: one responsibility per class
class Invoice { calculateTotal() { /* ... */ } }
class InvoiceHtmlFormatter { format(invoice) { /* ... */ } }
class InvoiceRepository { save(invoice) { /* ... */ } }
Billing logic changes when tax rules change. Formatting changes when the design team updates a template. Storage changes when the database migrates. Three stakeholders, three reasons to change, three classes.
How to spot a violation
- The class name is vague, or contains "and," such as
UserManagerAndValidator or a generic catch-all like Utils.
- A change request from one team consistently touches the same file as an unrelated team's changes.
- Testing one behavior requires mocking dependencies that have nothing to do with that behavior.
- The class grows every sprint, regardless of which feature is being built.
SRP compared to the other SOLID principles
| Principle |
Focuses on |
How it differs from SRP |
| Open/Closed |
Extension without modification |
SRP is about the scope of a responsibility; Open/Closed is about how you extend it safely |
| Interface Segregation |
Shape of a contract |
Interface Segregation is SRP applied to interfaces specifically |
| Dependency Inversion |
Direction of dependencies |
Orthogonal; a class can have a single responsibility and still depend on concrete classes it should not |
For the full picture of how these five fit together, see SOLID principles explained in 2026. Once a class is properly scoped to one responsibility, dependency inversion is usually the next thing worth fixing.
When splitting goes too far
The failure mode in the other direction is real: five classes, each with one method, spread across three files, for logic that is only ever used in one place. Tracing a single bug now means opening four files instead of one. Split along genuine axes of change, not just to hit a stylistic target of small classes. If two pieces of logic have never changed independently and there is no reason to expect they ever will, they may belong together.
FAQ
Is SRP the same as having short classes?
No. A short class can still mix unrelated responsibilities, and a longer class can be perfectly cohesive if every method serves the same purpose.
How do I know if two responsibilities are actually one?
Ask whether they change for the same reason, driven by the same stakeholder. If they always change together, they are probably one responsibility; if they change independently, split them.
Does SRP apply to functions, not just classes?
Yes. A function that validates input, calls an API, and formats the response has three reasons to change, the same problem at a smaller scale.
What is the difference between SRP and cohesion?
Cohesion describes how related the elements inside a module are, in general. SRP is a specific, narrower framing of cohesion, focused on the single axis of "who causes this to change."
Where to go next