Why Dependency Injection Is a Good Thing for Us, the Programmers

It’s all about loosely coupling. Let’s take a short coffee break in which I’ll explain it all.

Tal Kanel
Level Up Coding

--

Photo by Christophe Hautier on Unsplash

The examples are written in Kotlin but don’t make use of its special syntax capabilities so that every programmer will be able to understand.

What if our coffee machine wasn’t at the coffee station? What if instead, there was an empty space, and every time we wanted to drink coffee, we would have to construct the machine from scratch.

In software, everything runs a million times faster than reality, so it is legitimate to write code like this:

The problem though is that, in reality, no coffee machine can be built with an empty constructor. While construction performance might not be a factor, the construction complexity involved when using the coffee machine certainly will:

Can you tell by that code what the programmer is doing on her break?
Should a programmer return to work without drinking coffee just because she failed to construct a coffee machine? And how would it be possible to talk with all of these providers before drinking the coffee in the first place?
All of these are now the concerns of the poor programmer, who only wished to drink her coffee.

But you can move it all to another class that is responsible to create a coffee machine, right?

Good idea. This is exactly what the Factory design pattern is all about.

It cleans the code, but sooner or later it will have to change again. That’s because we, the programmers, are spoiled: We like to taste coffee from different machines that are not necessarily constructed in the same factory.

So as you can see, the Factory postpones construction complexity but does not make it disappear.

Ok. So what is your suggestion?

In real life, tool construction and its usage are two different processes segregated from each other. Humankind has always taken advantage of that. Think about it. Did the prehistoric-man build his spear just before he was about to stab the mammoth?

Our programmer doesn’t need to be busy in coffee machine construction during his break. She surely doesn’t need to bring a new machine from the factory. A coffee machine is just a tool used by the programmer to quickly make the coffee so that she could get back to the real work: writing code!

Nice theory. What does Dependency Injection have to do with that?

Dependency Injection is an architectural approach in which the construction code of classes and their usage are segregated systematically. How? There are several techniques, but one of them is construction dependencies inversion. It means that the CoffeeMachine construction shouldn’t be tightly coupled to the Programmer who uses it. Instead: The Programmer’s construction, unintuitively, should depend on the CoffeeMachine:

But doesn’t this just move the coffee machine construction to the class that holds the Programmer?

Not necessarily. Take for example a SoftwareCompanyX who wishes to hold aProgrammer: By following again Dependencies Inversion Principle, we will just make the SoftwareCompanyX’s construction depend upon the Programmer instead of tightly coupling the Programmer’s construction to the SoftwareCompanyX:

This is great because the Programmer can move easily to another SoftwareCompany and take the coffee breaks there. All she will need is someone who provides her a reference to the CoffeeMachine, and she’s back in business!

Are you kidding me? Eventually, someone will have to construct everything

Exactly! This someone will be the only one who needs to handle construction details for one particular cluster of classes. This will also be his single responsibility. This root of composition is what is known in most dependency injection frameworks as Module.

So the SoftwareCompanyModule is taking care of connecting everything and exposes externally only the SoftwareCompany.

Interesting. So why do I need a Dependency Injection framework?

There are still some questions that need an answer:

  • Who should instantiate a module?
  • What if a module depends on other modules?
  • How to share the same object instance in several places?
  • What about unit testing?

Dependency Injection frameworks help with these challenges, so you can focus on your own domain challenges instead of reinventing the wheel.

Coffee break is over now. Thank you for listening, and I hope you learned something new. I’d love to hear your thoughts and answer questions on this topic that you might have.

--

--