Quote of the Day

more Quotes

Categories

Buy me a coffee

The Single Responsibility Principle

Published May 25, 2021 in Architecture , Design Patterns - 0 Comments

Recently, I read the book “Clean Architecture” by Robert C. Martin. Overall, this is a great book with a wealth of information on software design principles to guide developers to build scalable, maintainable and flexible applications. A core part of the book discusses about six design principles which together make up the acronym SOLID.

The SOLID acronym represents the six principles:

  • S: The Single Responsibility Principle.
  • O: The Open Closed Principle.
  • L: The Liskov Substitution Principle.
  • I: The Interface Segregation Principle.
  • D: The Dependency Inversion Principle.

In this post, I give a recap of the Single Responsibility Principle, which is the first one in SOLID.

I have heard of the Single Responsibility Principle before reading the book. However, the way I understood the principle was that a class or function should just do one thing. This understanding is not accurate. In fact, the author explains that a module should only change when a user or a group of user requires that change, which the author generalizes and refers to as an actor. Examples of an actor could be a CFO, CTO, Finance department, DBA etc …

A module should be responsible to one, and only one, user or stakeholder.

Clean Architecture A CRAFTSMAN’S GUIDE TO SOFTWARE STRUCTURE AND DESIGN, by Robert C Martin.

The book gives an example of a class which violates the SRP. The Employee class is for managing employees and have methods like calculatePay(), reportHours() and save(). The Finance department has a say in how the calculatePay() works. However, it does not need to care about the reportHours() which the Human Resources department relies on for its reports. Both departments do not need to concern with how the save() method works to persist the data, as that is for the DBA .

Clearly, the Employee class violates the single responsibility pattern because it is responsible for multiple actors: The Human Resources department, the Finance department and DBA . Now, whenever one of the departments requests a change which result in changes to the Employee class, those changes can potentially impact the other departments even those they don’t want or need the changes. The author gives an example scenario.Initially, both the Finance and Human Resources department have the same rules to determine the number of regular hours out of the total hours the employee has worked. In the codes, the calculation of regular hours reside in a common method, regularHours() which both the calculatePay() and the reportHours() call. After sometimes, the Finance department changes the number of hours it considers as regular hours for the purpose of paying an employee. Upon updating the regularHours() method to implement the change and releasing to production, the app no longer produces correct reports for the Human Resources department because the rules are no longer correct for them.

Per the Single Responsibility Principle, we should extract the three methods into separate classes. The diagram below shows an example of a way to accomplish this.

Separate functionalities that change for different reasons

The Employee classes just delegate to the different classes to do the calculation. Furthermore, we can implement the different implementations of regularHours() for the different departments and relate them together via interfaces.

In summary, the Single Responsibility Principle encourages us to separate codes that change for different reasons so that when we make change to an existing module, we avoid breaking other modules that do not have to do with the change.

References

Clean Architecture: A Craftsman’s Guide to Software Structure and Design (Robert C. Martin Series)

Uncle Bob’s blog: Single Responsibility Principle

No comments yet