DEV Community

Hossein Molaei
Hossein Molaei

Posted on

SOLID Principles from the Perspective of Robert C. Martin

Single Responsibility Principle (SRP)

According to Uncle Bob, the Single Responsibility Principle (SRP) can only be applied correctly when you clearly identify the system’s actors.

“A module should be responsible to one, and only one, actor.”

Sometimes, the best way to prove a principle is to explore what happens when it’s violated.

Let’s look at a common example:

  • The calculatePay() method is defined and used by the Accounting department, which reports to the CFO.
  • The reportHours() method is used by HR, reporting to the COO.

  • The save() method is managed by DBAs, under the CTO.

Image description

At first glance, it might seem that the class follows SRP. After all, each method has a single job. But in reality, this is a clear violation of SRP. Why?

Because placing these three methods in a single class connects three different actors — meaning changes from one team might affect the others unintentionally.

⚠️A Real-World Scenario
Imagine both calculatePay() and reportHours() share a helper method called regularHours().

This method might seem like a single responsibility function. But what happens if the accounting department wants to change how overtime is calculated? They modify regularHours() to meet their needs.

But here’s the issue: HR is also using regularHours() — and they’re not aware of the change. The accounting team runs their tests and everything seems fine. But a few weeks later, HR starts complaining about inaccurate reports.

By the time the issue is discovered, the organization may have already suffered from incorrect data and misinformed decisions.

SRP tells us that this could’ve been avoided by separating responsibilities by actor.

Image description

👨‍💻 Parallel Development Chaos
Now imagine two developers working on this class:

One updates calculatePay() for the finance team.
The other updates reportHours() for HR.
When it’s time to merge, they run into conflicts — despite modern version control tools being quite advanced, merge conflicts in shared classes are still risky and can introduce subtle bugs.

✅** A Better Design**
One practical solution is to separate data from behavior. Instead of one large Employee class, you split responsibilities:

PayCalculator handles payroll logic.
HoursReporter manages working hours.
EmployeeRepository deals with persistence.
All of these classes can access a shared EmployeeData structure — a plain data holder without any business logic.

Each class contains only the source code necessary for its own responsibility. They are not aware of each other, reducing the chance of accidental overlap or unintended coupling.

Image description

💡 Facade to the Rescue
You might object: “Now I have three classes to instantiate and track!”

That’s fair. A common approach here is to use the Facade Pattern — a single class that hides the complexity of the subsystem and offers a simplified interface to the outside world.

So your application deals with one class, but under the hood, responsibilities remain separated.

🧠 Final Thoughts
The Single Responsibility Principle should be enforced not just at the method level, but throughout the entire architecture — from the top down.

Every actor in the system should have a corresponding class, with focused methods that serve only that actor’s needs. This leads to a system that is easier to scale, test, and maintain.

SRP isn't about writing fewer classes — it's about writing better ones.

Taken from the book Clean Architecture by Robert C. Martin

Translated by artificial intelligence from Persian to English.
Author : Hossein Molaei

Top comments (0)