David Wheeler (1927-2004) was something of a computer science folk hero around Cambridge. You think object-orientation was a neat idea? He invented the subroutine. Academics would tell stories of having conversations in which they’d describe some particularly thorny problem they were trying to solve, only to be met with, “Oh yes, I remember that: I never got around to writing a paper, but I’ll give you my notes on how I dealt with it.”
But he’s most famous for saying “Any problem in computer science can be solved with another layer of indirection.”. You’d have thought inventing functions would be more memorable, but actually it turns out that pithy remarks win out where posterity is concerned.
SOLID is all about abstraction. Let me express them in those terms:
- Open/Closed: Make stable abstractions
- Liskov: Don’t break your abstractions
- Dependency Inversion: Don’t take dependencies on concretions, including on object creation
- Interface Segregation: Make your abstractions as small as possible
Now, abstraction is useful precisely because it introduces indirection. Single Responsibility isn’t explicitly about abstraction, but applying it will introduce more indirection into your code. It’s exactly this that delivers the benefits of SOLID.
But that will usually create another problem
Of course, Prof. Wheeler didn’t end the quote there. Someone misquoted it as “Any problem in computer science can be solved with another layer of abstraction, except too many layers of abstraction.” Multiple layers of indirection can be quite painful to navigate, as anyone who’s stared as Castle Windsor’s code for the first time will attest.* This is a huge barrier to acceptance. I’m proud to say that I’ve managed to convince a number of developers of the utility of SOLID, but the fact remains that many just see it as unnecessary complexity. One complaint that I often encounter basically comes down to “F12 doesn’t work.”
Now, someone smarter and funnier than I am described not using dependency inversion as like soldering a lamp directly into the wall. This sounds ridiculous but let’s talk a bit about the benefits of soldering it. Well, figuring out your wiring is really easy. It never changes** and tracing your circuits is really easy. If you’re dealing with the plug next to the sofa, it’s got a reading lamp in it. It’s never a phone charger. When you switch on the reading lamp, you’re guaranteed it’s going to work and you’re not going to have to mess around unplugging whatever the last guy was using. SOLID code, by contrast, looks like tangle of wires the first time you see it.
Tracing the circuit in old-school code is pressing F12 in Visual Studio. SOLID breaks F12. You know the old saying that when all you’ve got is a hammer everything looks like a nail? Well, imagine you’ve got a screw and, instead of being able to whack it in, your hammer didn’t work at all. You might well come to the conclusion that there was something seriously wrong with this funny-looking nail. If you don’t have a key press for “go to implementation of method” like in ReSharper, you’re going to find that the only way to trace the execution flow is with a debugger. Equally, if “Find Usages” doesn’t understand that a method may be called because it’s an implementation of an interface, you’re going to find SOLID code harder to navigate. Never mind the cost of writing all of those single responsibility objects when you can’t press “Alt-Enter Enter” for the obvious bits. And I’ve only just scratched the surface.
Yes, you can do SOLID in Notepad and No, this isn’t the only barrier to adoption, or even the biggest. Still, it’s well worth bearing in mind that tooling matters. I kid you not, I’ve seen code get rewritten from SOLID style to something that works better with F12. If you want to get people into proper object-orientated design, you could do worse than starting with getting ReSharper on their desks.
[Disclaimer: I have no financial or personal interest in JetBrains; they’ve never even offered me free stuff.]
*Or StructureMap, or NHibernate, or pretty much any well written open source project.
**at least, not until requirements change, but that’s the point…