In computer programming, the term SOLID is a mnemonic acronym for five design principles intended to make software designs more understandable, flexible and maintainable (thanks Wikipedia) – but what does that actually mean?
Here’s the breakdown:
(S)ingle Responsibility Principle
(L)iskov Substitution Principle
(I)nterface Segregation Principle
(D)ependency Inversion Principle
There you have it, follow these principles and you’ve begun your path to clean design.
In this series, we’re going to try to really understand each one of the principles.
SRP – You had one job…
The Single Responsibility Principle is probably the least understood because the name seems so straight forward and simple. All of our classes and methods should do only one thing…easy enough.
However, “do one thing” and “responsible for” are two totally different animals.
While “do one thing” works perfectly for methods, this isn’t the Single Responsibility Principle (Clean Architecture – Robert C. Martin).
Methods SHOULD do only one thing, and have a good name to describe that one thing. Classes, however, dance more to the tune of the actual Single Responsibility Principle, which has been phrased as : “A module should have one, and only one, reason to change.”
What’s a reason to change?
Ok, so maybe DoAllTheThings() was a bit of an exaggeration. There will surely be more than one method in the Employee Class. We need to ReportHours(), CalculatePay(), and do all sorts of other things.
This structure should be making you cringe. ReportHours() is specified by the Human Resources Department, which needs this information for more than pay. CalculatePay() is specified by the Accounting Department, who is really just concerned with the regular and over-time hours worked on file, and how much they need to dish out.
I like this version of the Single Responsibility Principle:
“A module should be responsible to one, and only one, actor”
An actor would be a cohesive group of people(i.e. users or stakeholders). In this case, each department is a seperate actor.
In the beginning, ReportHours() and CalculatePay() shared a common algorithm for calculating non-overtime hours. In the interest of not producing any duplication, the developers put this golden algorithm into the RegularHours() method – with is then used to report hours AND calculate pay. After the meeting this morning, this developer starts on his task of changing the algorithm that is responsible to Accounting. This developer finds Calculate Pay() and tweaks RegularHours() to suit the new changes.
He doesn’t notice that RegularHours() is also called by ReportHours() and the algorithms needed now differ…
Again, Accounting is just concerned with the hours on file and the numbers work.
But it cost Human Resources plenty….
This could have been avoided with the seperation of data from the methods. Employee Class is now really Employee Data – a simple data structure with no methods. New classes are created (HoursReporter contains ReportHours() and PayCalculator contains CalculatePay()). Neither class knows what the other is doing, and a change to one would not affect the other, since each class holds ONLY the source code necessary for its particular purpose. This is where it diverges from “do one thing”, since you won’t have many little classes with one method each.
In Clean Architecture: A Craftsman’s Guide to Software Structure and Design, Robert C. Martin uses the Facade Pattern to counter-act the downside of now having multiple classes to instantiate and track.
In the next installment of the series, we’ll be diving into the Open/Closed Principle.
Until then, happy clean coding!
*Comic created using Pixton