In this guide we’re going to walk through the final element of the SOLID Development pattern, the dependency inversion principle.
If you have had a difficult time understanding some of the other SOLID guides you’ll be happy to know that this principle is probably the most straightforward.
Dependency Inversion Principle in the Real World
The reason why I think that the dependency inversion principle is easy to understand is because it relates to a real world pattern. Before we jump into the code we’re going to look at how a large company is structured.
Let’s imagine that you’re the CEO of Coca Cola. As the CEO of a multi billion dollar company you will have a number of responsibilities. Some of these tasks might be:
- Managing shareholders
- Making strategic acquisitions
- Deciding which markets to enter
- Along with a number of other high level decisions
Now let’s look at what you wouldn’t do as the CEO of Coca Cola. You wouldn’t:
- Drive a truck and make product deliveries
- Pick SEO keywords for the corporate website
- Work on tax rate calculations for the accounting system
- You get the idea…
As a CEO it would be your job to manage the organization and delegate responsibilities to the executives that report to you. If you spent your time with low level work like making deliveries to 7-11 you wouldn’t be able to properly manage the company.
Dependency Inversion Principle Definition
In a nutshell this is how the dependency inversion principle works.
The definition for the dependency inversion principle is that:
“High level objects should not depend on low level implementations”
In the same way that the Coca Cola CEO shouldn’t double as a truck driver, high level code shouldn’t perform low level duties.
Dependency Inversion Principle Code Example
For our code example we’re going to take a look at how the Ruby on Rails framework uses the
ActiveRecord is a powerful module that allows applications to interface with the database.
What do you think would have happened if the developers who built the Rails framework attempted to place specific implementation details in the framework? For example, what if they added a database query for
users? It would essentially render the framework useless, because it would only work if developers built out a
User class that matched the vision of the Rails developers.
Thankfully the Rails dev team chose to follow the dependency inversion principle. If you analyze the ActiveRecord module source code you’ll see that the code is simply concerned with high level functionality. This means that
ActiveRecord will let you do things such as:
- Search for records in a database
- Allow you to call data validations
- Utilize callbacks for automated behavior
- And additional high level tools
Inherited Classes to Manage Implementation
So what does the other side of the equation look like? If the parent class, in this case
ActiveRecord, manages the high level behavior, let’s take a look at a child class.
Here is a class called
User that inherits from
ActiveRecord::Base. This class contains implementation details, such as:
- Listing out specific attributes
- Mapping the
Userto other models in the application
- Defining data validations for attributes that the
So in review, in our code example:
ActiveRecordmodule is like the application’s CEO. It manages high level functionality, with zero implementation details. This allows the module to be used for any type of application and for all models inside an application.
- While the
Userclass is like one of the app’s workers. It focuses on the low level implementation details. It listens to the
ActiveRecordparent class and follows the guidelines laid out. Much like how an employee listens to a CEO’s instructions.
Overall the dependency inversion principle is a powerful design pattern that allows you to build scalable code that can be leveraged throughout an application.
I hope that this has been a helpful guide to understanding SOLID’s dependency inversion principle, and good luck with the coding!