Dependency Inversion Principle Explained and How Tutorials Get It Wrong

The dependency inversion principle is more than just abstractions and implementations.Image by Giedrius KristinaitisLet’s talk about the dependency inversion principle. More specifically, let’s explore what the dependency inversion principle is, and ho…


This content originally appeared on Level Up Coding - Medium and was authored by Giedrius Kristinaitis

The dependency inversion principle is more than just abstractions and implementations.

Dependency Inversion Principle
Image by Giedrius Kristinaitis

Let’s talk about the dependency inversion principle. More specifically, let’s explore what the dependency inversion principle is, and how it’s often presented in the wrong way and not fully explained.

What the Dependency Inversion Principle Says

The dependency inversion principle is not as easy to understand as it might seem. There are a lot of interpretations that get it wrong. The principle states that you should depend on abstractions, not implementations.

What does that tell to an average developer who hasn’t even heard of the SOLID principles? They immediately think of interfaces/abstract classes and their implementations, which makes sense, and they think that they can’t use concrete classes as dependencies in their code.

What results from that is the creation of an interface for everything, literally every single class, because, after all, you need to depend on abstractions, and interfaces are abstractions.

Such thinking treats the principle as a hard rule and doesn’t focus on what actually matters.

Biggest Dependency Inversion Principle Mistake

What people often miss is literally the name of the principle. Tell me, do “depend on abstractions, not implementations” and “dependency inversion principle” sound like the same thing? They don’t if you don’t dig deeper. When some people think of the principle they think about depending on abstractions, while completely missing the dependency inversion part.

What bugs me is the way the dependency inversion principle is being sold in a lot of courses and tutorials. All you see is an example where there’s an interface, and then there are 2 implementations of that interface, and the usage of the interface is literally presented as the dependency inversion principle. As I said, completely missing dependency inversion itself.

Polymorphism disguised as the dependency inversion principle

Let’s introduce another concept called polymorphism into the mix. What is polymorphism? Polymorphism is the use of a single symbol to represent multiple different types.

What can represent that symbol? Interfaces/abstract classes both can be used as that single symbol. The implementations of an interface are the different types that are referred to by the single symbol, which is the interface.

Doesn’t that look an awful lot like what’s being sold as the dependency inversion principle?

Plain polymorphism is often sold as the dependency inversion principle.

Dependency inversion is more than polymorphism

The principle is more than just polymorphism. Do you think the author of the SOLID principles was uneducated enough to just coin a new term to define polymorphism? I don’t.

Sure, polymorphism definitely plays a part in the principle, it’s just not the principle itself. This is where the concept of dependency inversion comes in. Polymorphism is just used to achieve the inversion.

Dependency Inversion Principle Explained

The flow of control

Before I can explain dependency inversion I need to introduce one more concept called the flow of control.

What is the flow of control? The flow of control is simply the order in which a program is executed. Here’s an example:

Example of flow of control
Image by Giedrius Kristinaitis

The main method calls the render method in the Document class, and the render method in the Document calls the render method in the ScreenDisplay class. That’s the order in which the example is executed. In the example dependencies point in the same direction as the flow of control.

Dependency inversion

Dependency inversion means that the flow of dependencies is inverted and points in a direction that is the opposite to the flow of control. Here’s an example:

Example of dependency inversion
Image by Giedrius Kristinaitis

However, wait a minute. Doesn’t that still look like the classic interface and implementation example? It does. It also inverts the dependency as the Document does not depend on ScreenDisplay anymore, it depends on the DisplayInterface, and the ScreenDisplay also depends on the DisplayInterface. The classic interface example technically does invert the dependency as well (that’s rarely mentioned, too).

So how is it different from the classic example that’s missing the dependency inversion part and is just polymorphism? It’s not… yet.

The context of code modules matters

The last example does indeed invert the ScreenDisplay dependency, it’s just that the inversion doesn’t make much sense outside the context of modules, and that’s the mistake that the simplified tutorials and courses make, they don’t talk about modules.

What are modules? Modules are independent groups of related functionality, meaning, they are loosely coupled (well, that’s what you should be aiming for).

What’s the point of inverting dependencies, what does it help to achieve?

The main point is that it helps to make your modules truly independent. It helps to make pieces of your application independently deployable. When you have the ability to deploy independently, you have one of the required conditions of being able to develop pieces of your application independently (just being able to deploy independently isn’t good enough for independent development if you have to know details about what’s happening in other parts of the system, in short, when abstractions are leaking details).

Of course, there are more benefits that make development and maintenance easier. The fact that modules are independent is huge by itself.

The inversion in the last example doesn’t make much sense, because everything’s in the same module, which means that full independence is not there, because how can you independently deploy pieces if they’re in the same module? You have to deploy the whole module, so it beats the point.

How hard it is to deploy your whole application depends on your tech stack, so in some cases, it can be really hard to deploy the whole application, and it makes a lot of sense to make modules independent and invert dependencies.

For example, let’s say you program in a statically typed language where dependencies need to be known at runtime, and compiling the whole application takes hours. As you can imagine, it would be a lot easier if you could just deploy parts of it independently.

If you’re working with a dynamically typed language it might be as simple as just updating source code files and the whole deployment might be done in minutes. However, that’s not a reason to completely ignore the dependency inversion principle.

Here’s the updated example with code modules:

Dependency inversion example with modules
Image by Giedrius Kristinaitis

Now you can see what modules exist. The screen display module and the rest of the application can be deployed independently. The screen display is a low-level module that knows about specific implementation details, and it depends on a high-level module, which is the document module, which is the module with business rules and shouldn’t know about implementation details.

There are 2 things that should be pointed out.

First, why are the Document class and the DisplayInterface in the same module? It needs to be done in order to achieve full module independence. If it was put in any other module, it would make the high-level document module dependent on other module(s). The DisplayInterface is just an abstraction through which the document module can interact with the outside world.

Second, what’s up with the relationship between the main module and the document module? The main module depends on the concrete Document class, not an abstraction. Isn’t it wrong? If you treat the dependency inversion principle as a hard rule, then it is.

There’s no way to make literally all modules follow the principle because there must be at least one module that wires concrete implementations with abstractions, which is often the main module.

What kinds of modules are allowed to violate the dependency inversion principle is an article on its own for the future, so I won’t expand on that any more.

The dependency inversion principle is more than just polymorphism. When you’re talking about it you can’t ignore talking about modules and how they interact.

The statement “depend on abstractions, not implementations” is more than simply creating an interface for every class that doesn’t abstract anything and sits in the same module/directory as the implementing class(es).

The principle is called the dependency inversion principle for a reason, let’s not forget that, because when we do, we either over-engineer with useless interfaces, or under-engineer and completely ignore the principle where it’s a good fit.

It’s a bit sad that there are a lot of tutorials and courses that don’t talk about the concept of dependency inversion and modules at all.


Dependency Inversion Principle Explained and How Tutorials Get It Wrong was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Level Up Coding - Medium and was authored by Giedrius Kristinaitis


Print Share Comment Cite Upload Translate Updates
APA

Giedrius Kristinaitis | Sciencx (2022-10-25T02:51:07+00:00) Dependency Inversion Principle Explained and How Tutorials Get It Wrong. Retrieved from https://www.scien.cx/2022/10/25/dependency-inversion-principle-explained-and-how-tutorials-get-it-wrong/

MLA
" » Dependency Inversion Principle Explained and How Tutorials Get It Wrong." Giedrius Kristinaitis | Sciencx - Tuesday October 25, 2022, https://www.scien.cx/2022/10/25/dependency-inversion-principle-explained-and-how-tutorials-get-it-wrong/
HARVARD
Giedrius Kristinaitis | Sciencx Tuesday October 25, 2022 » Dependency Inversion Principle Explained and How Tutorials Get It Wrong., viewed ,<https://www.scien.cx/2022/10/25/dependency-inversion-principle-explained-and-how-tutorials-get-it-wrong/>
VANCOUVER
Giedrius Kristinaitis | Sciencx - » Dependency Inversion Principle Explained and How Tutorials Get It Wrong. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2022/10/25/dependency-inversion-principle-explained-and-how-tutorials-get-it-wrong/
CHICAGO
" » Dependency Inversion Principle Explained and How Tutorials Get It Wrong." Giedrius Kristinaitis | Sciencx - Accessed . https://www.scien.cx/2022/10/25/dependency-inversion-principle-explained-and-how-tutorials-get-it-wrong/
IEEE
" » Dependency Inversion Principle Explained and How Tutorials Get It Wrong." Giedrius Kristinaitis | Sciencx [Online]. Available: https://www.scien.cx/2022/10/25/dependency-inversion-principle-explained-and-how-tutorials-get-it-wrong/. [Accessed: ]
rf:citation
» Dependency Inversion Principle Explained and How Tutorials Get It Wrong | Giedrius Kristinaitis | Sciencx | https://www.scien.cx/2022/10/25/dependency-inversion-principle-explained-and-how-tutorials-get-it-wrong/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.