Right, I’m back onto the SOLID principles again, I apologise to those who are bored of this.
So the other day I was listening to the most recent Scott Hansleman podcast with Uncle Bob Martin where the conversation was about the recent handbag fight between Bob Martin and Joel Spolsky – as I discussed in a previous blog post. In this podcast Bob Martin talks about an issue Joel Spolsky raised with him on the StackOverflow podcast #41. An extract from the discussion from the StackOverflow (SO) podcast #41 is given below:
Spolsky: Bob, can you explain again the Single Responsibility principle? Because I don’t think I understand it right.
Martin: The Single Responsibility principle is actually a very old principle, I think it was coined by Bertrand Meyer a long time ago. The basic idea is simple, if you have a module or a function or anything it should have one reason to change. And by that I mean that if there is some other source of change… if there are sources of change out there one source of change should impact it. So a simple example, we have an employee, this is the one I use all the time…
Spolsky: Wait, wait, hold on, let me stop you for a second. Change, you mean like at run-time?
Martin: No. At development time.
Spolsky: You mean changes of code. There should be one source of entropy in the world which causes you to have to change the source code for that thing.
Martin: Yeah. That’s the idea. Do you ever achieve that? No.
Martin: You try to get your modules so that if a feature changes a module might change but no other feature change will affect that module. You try and get your modules so partitioned that when a change occurs in the requirements the minimum possible number of modules are affected. So the example I always use is the employee class. Should an employee know how to write itself to the database, how to calculate it’s pay and how to write an employee report. And, if you had all of that functionality inside an employee class then when the accountants change the business rules for calculating pay you’d have to change the employee, you’d have to modify the code in the employee. If the bean counters change the format of the report you’d have to go in and change this class, or if the DBAs changed the schema you’d have to go in and change this class. I call classes like this dependency magnets, they change for too many reasons.
Spolsky: Is that… how is that bad?
I kind of feel the same as Joel with this one and I’m afraid that Bob is not really convincing me here. Why? Let’s pursue an example for a second.
Suppose that I’m creating a class that outputs a file. In this class I extract data from a database, convert various bits of the data, then output this data to a file. So how many reasons has my class got to change? Well it looks like 3: the database can change, how I convert the data can change, and how the file is output can change. Hence according to the S in SOLID, each of these operations should be contained in a separate class. Let’s just remind ourselves what the S in SOLID stands for:
A class should have one, and only one, reason to change. [1]
Now if I am forced into making changes to either the database, data conversion, and file format, I make the changes to my class. What is wrong with that? I just compile the project again and distribute the binary. Simple. I can’t see any benefit in breaking this class up into 4 separate classes, there just seems no point, but according to the SOLID principles there is. Arguments from Bob like “Yeah. That’s the idea. Do you ever achieve that? No” are nonsense. It clearly undermines the need for such rules in the first place. There is no point having rules if you are not going to stick to them. Fudging a rule every time it doesn’t fit your argument implies that the rule doesn’t make sense in general.
The discussion in SO #41 then moves on to the WordPress plugin system where Bob comments on how having independent plugins are a great example of the single point of responsibility (I must stress it was not Bob’s example, he just went with it). Eh NO. I think that it sometimes becomes easy to forget what the S means. Let me just state it again: A CLASS should have one, and only one, reason to change. The plugin itself, which is represented by a class, may have lots of reasons to change. Again in the subsequent Hansel Minutes podcast Bob uses the term module, in the sense of say a jar file in Java or a dll in .NET, to describe building a set of components that adhere to the S in the SOLID principles. This is once again deviating away from the actual meaning of S.
OK, am I being pedantic about the definition? I don’t think so. If it doesn’t mean what it says, then change it; there are people out there that will follow these rules blindly, and having such a specific definition only encourages this.
I think a far better rule would state that a class should only be responsible for a single task, in my example that task is creating the file. This is completely different from a class that has only one reason to change. OK, it’s a lot less specific, and maybe harder to judge, but any decent programmer will have a feel for what a task is. Not only does this seem like a more sensible option, it’s what the plugin and the module argument ostensibly encourage. It seems to me this is the only true generalisation you can extract from Bob’s arguments and I think it would be much better if this is what the rule suggested.
Don’t get me wrong, there are times when you want a class to only have one reason to change, this is especially true when you are developing a framework where the source code is essentially immutable to the outside world, in this case class design becomes far far more important. However the SOLID principles are intended as a set of rules for every programmer to use, and as it stands, I’m sure that the S is causing more confusion, code bloat, and misguidance than it is providing benefit to those adhering to these rules.
Having rules are a great idea, but they also encourage people to follow them word-for-word. It’s easy to say they should not be followed religiously, but I’m sure that is what is expected. This coupled with the developer with poor judgement, little experience and lots of blind faith, can leave us all wondering why we are even entertaining all this.
References
[1] http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod