And so, after five newsletters, we come to the final episode in my series on the SOLID principles.
The D in SOLID - The Dependency Inversion Principle
Let's continue our discussion of the SOLID principles. Today we'll close out this series by looking at the D in SOLID: the Dependency Inversion Principle.
This can be expressed in two steps:
- First, High-level modules should not depend on low-level modules; both should depend on abstractions.
- Second, Abstractions should not depend on details; details should depend on abstractions.
So we get the references to dependencies -- this depends on that -- but where does the inversion come from? Let's illustrate.
Back in the first part of this series, I gave an example of my binary tree painting code. In essence, given a binary tree this code would paint a visible representation of the tree so that we could look at it and understand properties of the tree (this node is a child of this one, and so on).
My original code failed the Single Responsibility Principle (navigation code and drawing code were intermixed) and also failed the Open-Closed Principle (the code only worked for one type of graphics context and I couldn't extend the behavior without altering the code). Let's take another look at that last one.
In essence, the code that drew each node or edge was dependent on one particular graphics context: the normal drawing code in .NET. My high-level "paint this node" code depended on the low-level details of how painting was implemented in System.Drawing.
I indicated at the time that the solution was to abstract out the painting into some idealized interface to a graphics context: set one up, draw a line, draw a filled circle, etc. What we're doing is inverting the dependency: instead of depending on a concrete implementation, I should be depending on an interface. Then, using the Liskov Substitution Principle, I could write an implementation of that interface that would stand in perfectly for the interface. The two modules (high level tree painting and low-level drawing a node) no longer need to know about each other: instead they "communicate" through an abstraction.
Once we have such dependency inversion, we're on a roll. We can test classes independently of each other. We can "mock" or "fake" interfaces for the intents of testing the class in question. Classes we write don't have to depend on setting up a huge database, we can fake the abstraction.
Or even better: we can set up factories to produce concrete behavior at run-time, driven by configuration files. We can use injection frameworks to provide data and behavior to applications that had no idea such data or behavior existed. Ninject, Spring.NET, Castle Windsor, and so on, here we come.
Of all the principles in SOLID, I feel the Dependency Inversion Principle is possibly the most important, and also possibly the hardest to convince someone to adhere to.
But, oh, the benefits if you do so.
(You can watch the video here.)
Yes, this principle is important, but like all of the SOLID principles can so easily be taken to extremes. (A really funny take-down (written using Java) can be read here.) Nevertheless, I feel the Dependency Inversion Principle (DIP) leads to much better, more readable code, than the alternative in “real-world” programs. Certainly, when I first came across it, I consciously changed the way I write code to make it apply. I didn’t necessarily use any injection frameworks as I mentioned above, but certainly, along with a switch from using an inheritance model to an interface model, I became more aware of how my code became more legible.
Remember, the whole series is based on papers written by Uncle Bob (Robert C Martin). Click here for the PDF on DIP.
I hope you enjoyed this series on SOLID as much as I did when writing/presenting it. Jeff and I did the whole set in one recording session (you can possibly tell: I think I look a little frazzled in this last one). Next time, we’ll talk about something else.
Just a quick inline “advert”: Gary Short, tech evangelist for our Frameworks, has a great talk on SOLID principles and how they relate to Technical Debt. If he’s presenting this at a meeting near you, I’d recommend you go and listen in. Well worth your time.