The Single Responsibility Principle (SRP) says:

A module should be responsible to one, and only one, actor

where

  • a module is a set of cohesive set of functions and data structures
  • an actor is a single, or a group of people who require a change (of functionalities)

Basically, the SRP says that the code should be separated in modules based on which actors use that code. This is consistent at different levels:

  • class level (OOP)
  • module level (library, package)
  • service level (microservices, bounded contexts)

Example of not following SRP

A class Employee with methods used by different actors

  • calculatePay accounting department
  • reportHours used by hr department
  • saveEmployee used by database admins

Because the methods are in the same class, a developer might be tempted to merge common code (e.g. regularHours, a common algorithm for calculatePay and reportHours). This could lead to errors down the line when one of the two actors ask for a change, that will affect the other method too.

The solution is to split the employee class in multiple classes, one for each actor, such that there are no conflicts and code related to one actor stays in its own class. If necessary, the split can be “covered” with the Facade Pattern. This will create a bit of duplication, but it’s actually better for maintainability if the duplicated behaviours belong to different actors.

Info

The solution in the book splits only the behaviour classes, and keep the employee data as its own separate data structure.

In my opinion, this leads to an anemic domain model.

I think the principle can be further exploited by splitting/duplicating the data too! This is the principle behind bounded contexts and microservices.