Dependency Inversion Principle:

Seanlowcy
Seanlowcy
Nov 2, 2020 · 5 min read

“All problems in computer science can be solved by another level of indirection” Butler Lampson

Well… not all I bet but probably a lot of them! What does ‘indirection’ here mean? It actually means the act of referencing something (an object etc) instead of the actual value itself. How does it come into play here? —While not the same meaning of simply setting up an abstraction layer, the key idea is there. Simply put, it may benefit us to set up some sort of intermediary reference instead of directly interacting with an object. In this case, an abstraction layer.

The Dependency Inversion Principle (DIP) further emphasizes this point. It is a principle that encourages further abstraction such that higher-level modules are not dependent on lower-level modules. But I’m getting a little ahead of myself… Before we talk about the specifics - a little background about DIP:

What is DIP?

DIP is one of the 5 SOLID principles promoted by Robert C. Martin.

DIP is basically the idea that high-level modules/implementations should not depend on lower level modules/implementations. If that is the case — that our high-level modules depend on lower level modules means that there is an inversion of dependencies! Hence the name of the principle.

The Idea behind DIP

The idea behind DIP is to promote higher abstraction of lower-level modules such that should the lower level modules change, the higher-level modules should not be affected.

Well, you may ask why should we not depend on lower level modules… Is it really that bad?

Well, I think the best way to explain this is through an example!

Let's say that you are creating an e-commerce application. On your e-commerce application, you have to install a payment gateway (If not how else are you going to earn $). There are multiple options such as Stripe and Paypal. So let's say that you decide to use Stripe’s API first to implement the payment gateway on your application!

And so look at the code below:

public class Store {
Stripe stripe;

class Store() {
this.stripe = new Stripe();
}
public void sellItem() {
this.stripe.processpayment();
}
}
class Stripe() { public void processpayment() {
System.out.println(“Earned $10 through Stripe”);
}
}
UML Class diagram of Store and Stripe relationship

In this case, you are directly calling methods from the Stripe API itself. You may ask well but it works right?

There’s an issue here — do you realise that the higher-level module (Store) is depending on the lower level module (Stripe payment gateway)?

What if Stripe suddenly goes under maintenance but your store is still online! There are still many people who want your product and so you have to implement a new payment gateway (Paypal). However what is happening now? There is an issue — we have to change the code from our Store class which is a higher-level module.

While this looks alright since it is a small class in this example, in a bigger application, there are definitely going to be multiple instances where our ‘stripe’ variable is used and the API is called. So that means we have to switch every single one of them. This could mean LOTS of time wastage, convoluted code and a huge amount of potential errors.

Solving the problem

So how do we avoid this problem? As mentioned above and to adhere to DIP, we should set up an abstraction layer!

public class Store {
PaymentGateway paymentGateway;
class Store() {
}
public void setPaymentGateway(PaymentGateway pg) {
this.paymentGateway = pg;
}
public void sellItem() {
this.paymentGateway.processpayment();
}
}
class Stripe() implements PaymentGateway { public void processpayment() {
System.out.println(“Earned $10 through Stripe”);
}
}
class Paypal() implements PaymentGateway { public void processpayment() {
System.out.println(“Earned $10 through Paypal”);
}
}
interface PaymentGateway { public void processpayment();
}
UML class diagram for Store, PaymentGateway, Paypal, Stripe

We set up an interface ‘PaymentGateway’ and we make our Stripe and Paypal classes implement this interface. An interface is basically a contract — when a class implements the interface, a class must use all the methods dictated by that interface. We also added a new method setPaymentGateway which allows us to reset our Payment Gateways if needed.

Now if Stripe goes under maintenance and we want to switch to Paypal we can simply reset our Payment Gateway with setPaymentGateway! Simple!

Thus as we can observe, our higher-level module (Store) is not directly dependent on any changes in lower level modules (Stripe or Paypal). Instead, it is dependent on an abstraction layer we have created. Now if Stripe goes under maintenance, we can switch payment gateways easily.

Thus we have now fulfilled the DIP principle — there is no more inversion of dependencies — our store does not depend on the Stripe or Paypal API directly. Instead, our Store now depends on an abstraction layer.

Further Notes

Also, a rather confusing quote you may hear about DIP is

Details should depend on Abstractions — not the other way around

Well, what does this mean? In our class previously we had our Store class depend on the Details of the Stripe API — since should anything happen to the Stripe methods, we might have to change our code in the Store class directly. In other words, previously our Abstractions were dependent on the Details. This should not be the case!

However, now, with the new PaymentGateway interface, the Details are dependent on the Abstractions. This is because the details of implementation in the Stripe and Paypal class are now dependent on the abstractions that we require — such as the ‘processpayment’ method. Now we can change the code in Stripe and Paypal accordingly depending on what further abstraction we need!

I hope you have enjoyed this little explanation on DIP! Do leave any thoughts you have about it in the comments below!

The Startup

Get smarter at building your thing. Join The Startup’s +792K followers.

Sign up for Top 10 Stories

By The Startup

Get smarter at building your thing. Subscribe to receive The Startup's top 10 most read stories — delivered straight into your inbox, once a week. Take a look.

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +792K followers.

Seanlowcy

Written by

Seanlowcy

The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +792K followers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store