Part of my SOLID programming principles series.
What is the Dependency Inversion Principle?
The Dependency Inversion Principle can be summed up in one simple quote “design for the interface, not the implementation”. The idea is that software is built by making simple objects and functions, which are then used by more complex objects and functions. This principle is a way to make it so that higher-level components are not dependent on any particular lower level component, thereby making it easier for parts of a program to be extended or switched out.
Benefits
The main benefit of this is another level of modularity in your programs. once an object is no longer dependent on another, either of the two objects can be replaced.
Applying the Dependency Inversion Principle
This is an example from 2 projects I recently had for my data structures class at the University of Georgia. The first project involved parsing a file of text, and providing a word histogram, which would display a list of words from the file, in alphabetical order, along with the number of times that word showed up. These words would need to be stored in a binary search tree. Here is a simplified, psuedocode example of the project:
class BinarySearchTree {
public getHistogram() {
//returns histogram
}
}
class HistogramGUI { private BinarySearchTree wordTree;
public getHistogram() {
return this.wordTree.getHistogram();
}
}
my next project was to again generate a Histogram from a text file, but this time using a 2-3-4 tree. Now I could have re-used code from the previous project, but now I have to re-write the HistogramGUI class to use a different kind of tree. Who knows what my next project is going to be? maybe I will have the same problem yet again, but using some other kind of data structure. The HistogramGUI currently has a depenency on the other class of BinarySearchTree. If we add an interface for being able to generate histograms, I can remove this depenecy, and make the HistogramGUI class more re-usuable.
Here’s the new structure to support both projects:
interface IHistogram {
public getHistogram();
}
class HistorgramGUI {
private IHistogram histogramGenerator;
public setHistogramGeneration(IHistogram generator) {
this.histogramGenerator = generator;
}
public getHistogram() {
this.histogramGenerator.getHistogram();
}
}
class binarySearchTree implements IHistogram {
public getHistogram() {
//returns histogram
}
}
class 234Tree implements IHistogram {
public getHistogram() {
//returns histogram
}
}
now you see that I can use the histogramGUI class with any class that implements IHistogram. If my next project called for the same problem with a B-Tree or a Red-Black tree or a simple array, it no longer matters to the histogramGUI class, as they are all now interchangeable. This gives you all the benefits of composing more complex objects from simpler ones, but allows you more flexibility. the histogramGUI class does not (and should not) care about how the data is generated.