Dependency Inversion: why you should NOT avoid it

Dependency inversion principle (DIP) is one of the SOLID concepts described by Uncle Bob in his book Clean Code. He defined Dependency Inversion Principle as follow:

Depend on abstractions, not on concretions.

That is a powerful concept, however, we usually avoid it due to laziness, thinking that is going to consume us time and his value is not worthy.

In this post I am going to talk about why we shouldn’t avoid DIP, why is important and how this can save our asses later in our projects.

TRY IT YOURSELF: You can find this post source code here.

Dependency Inversion Series

What we usually do

This is a typical example we find in any project:

A Service class uses a MySQL Repository to access the data base.

This approach has drawbacks:

  • Service and MySQLRepository are pretty coupled.
  • If we change MySQLRespository class and compile it, you must compile Service too.
  • Service depends on a concrect class, database access implementation.
  • We cannot deploy Service without MySQLRespository.
  • If we later need to change MySQL for any other database, you must change Service to adapt to the new class.

You might think “when will I change my database?, that won’t happen, if I choose MySQL, I stay forever with MySQL”. Well, you might haven’t worked for huge, complex projects, or you just like to lie to yourself.

Software requirements are always changing and evolving. Ten years ago, Oracle was our first paid database choice, today, there are more options, with pretty good features and solutions for a wide range of problems.

TRY IT YOURSELF: You can find this source code here.

What we should do… always

Let’s avoid to be lazy and get this done well.

Service class was depending on concretions, on MySQLRepository class. Now, we need the Service class to depend on abstractions, so, we invert the dependency.

Inverting the dependence

This approach has advantages:

  • Service doesn’t know anything about MySQLRepository (concretions), it only knows about an abstraction.
  • You can deploy Service in different time, in different ways, without dependencies against Repository implementations.
  • You might have multiple Repository implementations, and you could exchange one by other without affecting Service.

Now, as everything, this has disadvantages:

  • More code to maintain.
  • It is a challenge to find good implementation names.
  • And yes, more work.
Multiple Repository implementations

We are awesome, that is perfect… isn’t it?

Actually, not, not at all. We are missing an important part:

How and when do you create the Repository implementation object?

Service class could look like this:


public class Service{
  private final Repository repository;
  
  public Service(){
    this.repository = new MySQLRepository();
  }
}

Well, we just couple the Service class to the MySQL repository implementation, and we lost the work we did.

TRY IT YOURSELF: You can find this source code here.

Final Thought

Object creation is one way of coupling, and we should handle it in a different approach. In my next post, I am going to talk about the Main and the Abstraction concepts, its relation with Inversion of Control (IoC), how they combine to create decoupling software and help us to solve the object creation challenge.

If you liked this post and are interested in hearing more about my journey as a Software Engineer, you can follow me on Twitter and travel together.

8 comments

Leave a comment