Skip to main content

Problem understanding the Single Responsibility Principle [Resolved]

The SRP seens fairly reasonable when you first look at it. Every class should have one reason to change. Every class should take care of one thing. Right. But let's see this class:

Employee {

This class was used as an example by Robert C. Martin. He describes three responsabilities for this class; calculating pay that deals with accounting, save and find by id that deals with database & describe employee that deals with formatting.

My issue is that if you take these responsabilities and separate them into classes, then Employee will become a data structure. It won't do anything. If in the future you need it do something, you can certainly call that just another responsability and decouple it too. This means that essentially, this is procedural programming. You can say 'compose Employee of those classes and put wrapper methods in the Employee for them', but then you end up with chains of wrapping. Maybe it's good practice but it feels wrong.

Another issue is what you consider a reason to change. It can be anything. If you say 'this class changes when the program changes' then everything goes into a class. If you say 'this class changes when the last digit of the last serial code printed in the 23th of May, after a virgin has been sacrificed to the moon goddess, changes' then there's a trillion classes. Should I just guide myself by a class cohesion? Should I forget completely about this "one reason to change" buzzword?

Question Credit: Mister R.U.B.I
Question Reference
Asked April 16, 2019
Posted Under: Programming
5 Answers

After years of banging my head against the wall with the SOLID principles, I've been able to make sense of them by following these rules.

  1. It's not a "reason to change" until it actually does change.
  2. Two "reasons to change" are the same reason if they have a common cause.
  3. A class that doesn't contain code with control structures is exempt from the SRP. ;

The first rule prevents you from over-generalizing and making things harder than they need to be. If you find yourself changing a class and later changing it again for a different reason, it's time to refactor. Until then, don't worry about it.

The second rule constrains the definition of "reason". For example, let's say that we want to show the number of years an employee has been with the company next to their name. We're not tracking years of service now, so we need to add it to Save(). We also need to update DescribeEmployee() to display the number. While two supposedly unrelated methods are affected, there's a common cause, so that only counts as one reason to change.

The third rule makes it okay to have a "Main" class that does nothing but configure the app, instantiating objects and passing them to other objects. This class will change all the time for all different reasons. Ideally, most of the changes to existing code will be confined to this class. That's a good thing because for all intents and purposes, a class without control structures is just a configuration file.

credit: Doc Brown
Answered April 16, 2019

In your example you do not give the implementation of Employee, however we can guess that these methods do not actually do all the work themselves but call sub-component that have the responsibility of doing it. (eg employeeRepository save employee in db).

Here the responsability of Employee is to serve as an entry point or a facade for the operations done on Employee. Its role is to orchestrate this.

credit: maxence51
Answered April 16, 2019
Your Answer