Single Responsibility Principle
A class should have one reason to change, and a reason to change is a group of people who ask for changes.
Overview
The Single Responsibility Principle (SRP) is the S in SOLID. Robert C. Martin stated it as: a class should have one, and only one, reason to change. The word responsibility confuses people, because it sounds like one job or one method. Martin's own clarification is that a reason to change is a person, or a group of people, who ask for changes. A class that serves two groups will be changed by both, and each change risks breaking the other group's feature.
The idea is older than the name. David Parnas wrote in 1972 that a module should hide one design decision that is likely to change. Larry Constantine's cohesion, and the work of Tom DeMarco and Meilir Page-Jones, said the same thing in the language of structured design. SRP is that idea applied to classes.
Reasons to change are people
Martin's example is an Employee class with three methods. Each one is asked for by a different part of the business.
- calculate_pay() — finance — a payroll rule change is deployed with unrelated code
- report_hours() — operations — a report tweak can break pay by sharing a helper
- save() — the database team — a schema change forces a retest of payroll and reports
How to spot a violation
- The name needs "and" or "Manager" — UserManagerAndNotifier
- Methods that are never called together — compute_tax() and send_email()
- Imports from unrelated areas — one file imports the mailer, the ORM and a PDF library
- Different tickets touch the same file — a payroll fix and a report fix collide in review
- Describing the class needs "and" — it calculates invoices and prints them and emails them
The one-sentence test is the fastest: describe the class without the word "and". If you cannot, list who asks for each method and group the methods by that person.
Before and after
An Invoice class that computes, formats and stores. Three reasons to change in one place.
Split by reason to change: the pricing rule, the text layout and the storage each get their own class. The data stays where it was.
A tax change now touches only the calculator. A new PDF layout is a new renderer. Moving storage to another database changes only the store.
Not too small
SRP is not one method per class. A class with ten methods that all change for the same reason has one responsibility. The failure in the other direction is real: splitting a cart into CartAdder, CartRemover and CartTotaler scatters one rule over three files that always change together.
- the methods read and write the same data for the same rule — two groups of people ask for changes to the same class
- the methods always change in the same commit — a change for one feature keeps breaking another
- the class is easy to describe in one sentence — the sentence needs "and"
The unit is cohesion, which Constantine defined as how strongly the parts of a module belong together. High cohesion is what SRP is after.
What you will be able to do
- Explain a reason to change as a group of people, with an example.
- Spot a class that serves two groups and say which change would break which feature.
- Split it along those lines without producing a pile of one-method classes.
- Apply the same test to a function, a module or a service.
Interview questions
- How do you identify SRP violations?
- How do you apply SRP without an explosion of tiny classes?
- What is the difference between cohesion and SRP?
- Does SRP apply to functions, modules and services, or only classes?
- Refactor this class that violates SRP.
Sign up free to read the full topic
More Low-Level Design topics
Start free on Cariara · Coding problems · System design studio