Recently I had the privilege of attending an Agile Software Craftsmanship workshop given by perhaps one of the most influential people in my coding career, Robert C. Martin, or as he is better known, Uncle Bob.
While the workshop itself was definitely aimed at newer people to our trade, or those hovering around the edges of the Software Craftsmanship movement, I still found good value in attending.
A wide range of topics was covered, the programme for the next course can be seen here, but the chance to ask Uncle Bob some of the more curly questions that crop up over a career of working with various personalities was too good to miss.
So, after the first day of the workshop I asked Bob what he had planned for tea that night… When he replied that he had nothing special on I suggested we head out to a local London pub, down some ales with a meal and have a good old yarn.
What an opportunity !
SO after a few pints of guinness, and a great meal, the following topics were some of those discussed ;
Single Responsibility Principal
This is one of my pet peeves at the moment. Now, I think the SOLID principals are a great set of guidelines when it comes to building maintainable software but the one I think that gets misinterpreted a lot, and by extension does the most damage, is SRP.
The original definition, and the one I use almost exclusively when discussing SOLID, is Single Reason For Change, but at some point the words change and “Responsibility” crept in.
The problem with Responsibility is it’s a very loaded English word. Taken to its OCD limit, it means you can’t use something like the Repository pattern, because having Insert, Update, Delete and Get methods on the same class is very clearly way more that a single responsibility (!)
The damage this does, especially when coupled with the crack cocaine of dependency injection containers, is clear when you have to understand one of these projects and find yourself wading through a quagmire of interfaces and classes, each of which may only have a single method, and a single implementation … and a single class that actually uses the damn thing !
Two other measures of software quality that are often forgotten about while rabidly frothing at the mouth about Single Responsibility are Coupling and Cohesion. The breaking up of related elements that belong together, such as public methods on a Respository for updating and inserting records into FoobarInserter and FoobarUpdater more often than not results in shotgun surgery when a change has to be made.
Well, Bob agreed that the original definition he coined, Single Reason For Change, was not about “responsibilities” at all, but more about the code only being affected by a single actor.
So if you had code in a class that was impacted by changing requirements from, let’s say the publishing department due to the formatting of some data, and then also changing requirements from the legal department due to changes in law, then this would mean a class has more than a single actor that will cause it to change.
This doesn’t mean however that we just shovel everything into a single class per actor, and as with anything there are no black and white rules, however before you are tempted to split something out into a separate class ask yourself the following ;
What is the reason for change that would cause me to have to alter this class and no other class versus what is the reason for change that would cause me to alter this class and the other class I am separating its “responsibility” from ?
In the case of the Repository versus Database Commands it might go something like this
If I have a FooRepository, then the worst case scenario if the database table changes I need to edit a bunch of public methods in the same class, each of which have their own single reason for change at a more granular abstraction level. I have a single class to find.
Now I have a FooInsertCommand, FooUpdateCommand, FooDeleteCommand and whatever other implementations there might be. At best, the person has organized them into a namespace and following a naming convention… I hope… in this scenario if the database table changes I am reminded of Shalloway’s law, in that I can be sure I will only find the N-1 places that I need to change the first time around.
Using “Responsibility” in SRP also, ipso facto, leads to a place where you cannot have any sort of API classes, since they would naturally violate this.
Enough of my rantings for now, I will follow up with some more discussions on other software topics that Bob and myself discussed in future blog posts.