Skip to content

Dependency Injection will make you look cool

I love this quote:

“Dependency Injection” is a 25-dollar term for a 5-cent concept.

I love it so much that I posted it separately.

What on earth is Dependency Injection?

Every time I have to explain what is Dependency Injection, I can’t avoid picturing myself as one of those cheap comedy characters, torn between two little instances of myself siting on my shoulders, one wearing all white, the other one wearing all red.

The one in white is whispering to my ear “provide some background, start the Dependency Inversion Principle”. The one in red,though, will be jumping up and down, shouting “tell him about passing everything your class might need in the constructor”.

Yeah, I have a rich complex inner life.

The Dependency Inversion Principle

Let’s do the right thing, and start from scratch.

A. High-level modules should not depend on low-level modules. Both should depend on abstractions.

B. Abstractions should not depend on details. Details should depend on abstractions.

There you have it, the Dependency Inversion Principle in all its glory. Obviously, if you throw that to anyone’s face, you should expect at least some eye-rolling, if not some head banging (them banging your head against the nearest wall).

In a nutshell, what the principle states is that both high and low level components should depend on the same abstraction. More about that later…

Riiiiiight, but what is Dependency Injection?

Basically, it is a pattern. Not one of the patterns in the GoF, but a pattern nonetheless. A pattern employed to facilitate that both high level and low level components depend on the same abstraction, aka the Dependency Inversion Principle.

Riiiiiiight, would you mind providing an example, smartass?

First, no problem. Second, mind you colourful language, please.

But you have a point. Here is an example of a very simple multi-layer app. There is a service layer that performs operations against an specific service (a service might be an actual remote service, or just a file on disk, let’s assume for the shake or the argument that, in this case, it attacks a remote service), and a business layer on top of it that provides a domain-specific API.

Quite straightforward, right? Indeed. The problem here is, what happens if we need to change the way the service layer works? What if we want to grab the configuration from a file on disk, instead of a remote service, or even worse, decide what to do at runtime?

Yeah, we are in a bad situation. Why? Because there is a hard dependency here. The ConfigurationManager depends directly on the ConfigurationService. Those two classes are tightly coupled, the manager can not work without the service.

Sweet. You are good at describing code smells. What about a solution, please?

Sure, no problem. Dependency Injection to the rescue! No, wait! Dependency Inversion Principle to the rescue!

First, I will try to find an abstraction both the manager and the service can depend upon.

Second, I will make my service implement the ConfigurationService protocol.

Now here comes the part where we all facepalm in sync, because suddenly, the concept “Dependency Injection” makes sense. The Dependency (in this example, remember, it was the ConfigurationService) will be injected into the ConfigurationManager as a parameter in the constructor. But wait, there is more! The ConfigurationManager will not hold a reference to an specific dependency, but to an abstraction (the Configuration interface).

This last bit is important, so I am going to repeat it. The ConfigurationManager depends on an abstraction now. It is not aware of which actual service it is using, and it actually does not give a damn about it.

Summary

Dependency Injection decreases coupling, and improves the flexibility and modularity of all designs. And it is a neat term that will make you look cool if you use in front of your colleagues.

As usual, you can grab the source code on GitHub

One Comment

Leave a Reply

Your email address will not be published. Required fields are marked *