The Single Responsibility Principle (SRP) may be the most misunderstood SOLID principle of object-oriented design, so much so that Robert C. Martin (aka Uncle Bob), the proponent of these authoritative principles, published a blog post in May of 2014 to clear the confusion.

The most intuitive interpretation of responsibility in this context is a job. Classes have “jobs” to perform so it makes sense to argue that a class with single responsibility means it has one job. It’s easy to see how many people, including myself, would think of it that way. Search “single responsibility principle one job” on Twitter and you’ll see many think the same way, years after Uncle Bob’s illuminating blog post. Therein lies a possible cause for misunderstanding.

”This principle is about people”

In the book Agile Software Development, Principles, Patterns, and Practices published in 2003, Uncle Bob defined the Single Responsibility Principle as:

A class should have only one reason to change.

This is a more nuanced definition, steering away from the notion that a class should only have one job. A responsibility is defined as a reason for change. If a class is likely to be affected in the future by change requests of differing reasons, the principle suggests that the responsibilities should be split to separate classes. When faced with real-world scenarios, though, I still found this definition hard to grasp and apply.

What helped create a better mental model for me personally is captured in this statement from Uncle Bob’s aforementioned blog post that followed over a decade after the book:

This principle is about people.

A responsibility is an obligation to someone. A responsibility represents a person or group of people to which the program responds and is liable to. If we look at it this way, we can define the principle as:

A class should be responsible to only one actor.

We can think of an actor as a person or group of people that is a part of a single business function. Actors are stakeholders who have skin in the game. They are responsible for the failures of their respective domains. That’s why they request features or ask us programmers to fix a bug. They are the reasons for change.

The Customer example

Suppose we are developers of an app for a bank. We have a Customer class that maintains basic customer information and supports three methods:

Customer class

Then, let’s say all of the following events happened today:

Notice that three (3) C-level execs are about to get us fired. LOL. This is an exaggerated example but it begs the question: to whom is this class responsible to? There are three business functions that have a stake in this class. The class will change based on the interests of three different actors.

Thus, SRP suggests to split the class. There are many ways to do this. Here’s a good start:

Customer class split

Customer keeps the basic customer information while the different responsibilities are distributed to three separate classes.

If, for example, the Marketing Team requests a feature to allow certain promos to be applied only to specific customers, the business logic will be right at home in PromoService, which deals with matters concerning the Marketing Team’s promos.

PromoService new feature

Over time, each class will grow in complexity on their own while still catering to a single actor. Not only is the code less coupled, but we are also not introducing needless complexity and over-fragmenting code (which leads to this nightmare).

TL;DR

The common misconception about the Single Responsibility Principle (SRP) is that it demands a class to do one job. It is important to clarify that responsibility in this context doesn’t mean a job or a thing to do. It means reason for change or simply put, an actor to whom the class is responsible to. This distinction is important in understanding how SRP can help achieve the balance between maintainability and needless complexity.