The Single Responsibility Principle (Part 2)
Previously, we discovered how the Single Responsibility Principle (SRP), the first of the SOLID Principles, instructs us on how we should and shouldn’t write our classes.
I reused the canonical example from Robert C. Martin’s excellent book ‘Clean Architecture‘: We have a Employee
class in a payroll application responsible to three separate ‘actors‘—the IT, Accounting and Operations departments. And herein lay the problem—any changes to the Employee
class made by one of the departments might be at odds with the needs of one of the other departments. A modification of a shared helper method by the programmers in Accounting consequently broke expected behaviour in the Operations department.
SRP violations can express themselves as subtle, damaging bugs.
What are we to do? How do we fix this?
Let’s refresh our minds of what the (restated) SRP was about:
Each module should only be responsible to one actor.
How do we make class Employee
responsible to only one actor? We may need to break it up into smaller classes, each solely accountable to a single department’s needs.
How should we go about this?
Well, the public methods of Employee
are CalculatePay()
, ReportHours()
and Save()
. Each is responsible to a different actor—the Accounting, Operations and IT departments, respectively.
It makes sense to break up Employee
along these identified responsibilities, the public methods. But what should we name the new classes?
The names of modules should reflect the work that they do. In our case, it would make sense to have, say, a PayCalculator
, an HoursReporter
and an EmployeeSaver
. Those names are pretty good, I think. No?
Aside – No Noise Words
Please, please give your classes descriptive names that leave out meaningless noise words. Consider PayCalculationHelper
, HoursReportManager
and EmployeeSavingService
. Do these names convey more information than PayCalculator
, HoursReporter
and EmployeeSaver
? No, not really. Their wishy-washy naming reduces clarity and obscures meaning. Indeed, these unclear names may, over time, attract code that does not strictly belong. The often-used ‘Helper
‘, ‘Manager
‘ and ‘Service
‘ noise words detract rather than clarify a classes purpose and are best left out.
The classes after breaking up of class Employee
:
A couple of salient points:
- Notice that
PayCalculator
andHoursReporter
each has their own, independent version ofGetRegularHours()
. We got into trouble because a change toGetRegularHours()
by the Accounting department broke expected behaviour in Operations. BothPayCalculator
andHoursReporter
now have separate, independently changeable copies ofGetRegularHours()
. The Accounting and Operations departments calculate regular employee hours worked differently. We are forgoing DRY (Don’t Repeat Yourself) because it is appropriate, even required, for us to do so. - Our new collection of classes must not reference and call one another. If they do, then we will have re-established the original SRP violation.
Leave a Reply
Want to join the discussion?Feel free to contribute!