“Dependency Injection” in a JavaScript planet

In this article we will discuss about the “Dependency Injection” principle in Software Engineering and its adoption on JavaScript applications.

Dependency Injection ?

Dependency Injection analogy ;) — photo courtesy of https://pexels.com

Dependency Injection (also known as DI), is one of the best Software Engineering principles we can apply in software projects. According to Wikipedia:

In software engineeringdependency injection is a technique whereby one object (or static method) supplies the dependencies of another object. A dependency is an object that can be used (a service). An injection is the passing of a dependency to a dependent object (a client) that would use it. The service is made part of the client’s state.[1] Passing the service to the client, rather than allowing a client to build or find the service, is the fundamental requirement of the pattern.

https://en.wikipedia.org/wiki/Dependency_injection

DI in statically typed languages

Java was the programming language I have used for longer period in my young career. In 2009, one of my former university colleagues challenged me to switch from PHP to Java: “the promised land”… and somehow I ended up using Java for the next 6 years intensively in production.

Thanks GOD, the migration to Node.js 🚀came afterwards in 2015… and yet: If something I miss from Java, that is the “Spring IOC module” 😥

The Spring IoC container — https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans

There are certainly DI implementations for every programming language or stacks. For statically typed languages like Java or TypeScript, implementations are really impressive, due to the power of interfaces and modern OOP resources like annotations (see TypeScript example).

Let’s analyse a basic example in TypeScript using the inversify framework:

Declaring dependencies— https://www.npmjs.com/package/inversify

What have just happened:

  1. We have declared two injectable services (Katana and Shuriken) using their correspondent interfaces (Weapon and ThrowableWeapon).
  2. We have declared another injectable service that will receive two dependencies through it constructor, in concrete a Weapon and a ThrowableWeapon.

Then we create a DI container:

DI Container creation — https://www.npmjs.com/package/inversify#step-3-create-and-configure-a-container

And finally we resolve assembled dependencies:

Resolving dependencies — https://www.npmjs.com/package/inversify#step-4-resolve-dependencies

And VOILA, magic just happened!

The DI Container have instantiated the required objects and resolved their dependencies behind the scene. So instead of managing objects creation and their dependencies in our code, a “magic” container is doing this for us 🙌!

This process is a sub-set of a bigger design principle called “Inversion of Control”.


DI in JavaScript?

JavaScript is not a statically typed language, it does not support interfaces, neither variable type declaration. Certainly some of the magic of a DI container is simply not possible here, as the system can’t infer the expected dependency type in a “decent” way. 
However, DI is still possible using JavaScript!

Let’s analyse a basic example in JavaScript using the dizzy framework:

Creating an Expressjs application using Dependency Injection — https://www.npmjs.com/package/dizzy#examples

As types can’t be inferred using Class or Interface names, we can use the function parameters name to refer to the dependencies. Let’s get again into this process:

Resolving dependencies using function parameters name

While registering a service, we indicate the dependencies that are required to be resolved first, so we can instantiate the “app” service. Here we use the callback function parameters name to indicate the DI container what dependencies to inject🏌🙌.

Are we then using DI in JavaScript?

If you are a Frontend Developer this days, you are most probably using DI through TypeScript. Just to mention one example:

While DI is pretty used in one way or another for frontend applications (because here we produce a lot of objects 😉), it is not the same case for the backend. I tried to answer my self this question, and I found what I guess is the root cause:

Major backend web frameworks in JavaScript / Node.js does not use DI on their core, thus not in their documentation or “getting started” guides. It is simply not promoted as a good practice. Ultimately causing developers to think:

“Humm, adding a DI framework to rule my application setup might just not be correct!”

In my honest opinion: The adoption of DI techniques in JavaScript backend applications is low, and that is really sad!

As a positive example of promoting DI on the backend we can mention the Nestjs framework, although it is not so popular and uses TypeScript as a required language. Anyways 👏

Conclusions

“Dependency Injection” is only about benefits. Dozens of libraries are out there, ready to make it possible for the JavaScript language, both in the frontend and the backend.

So I want to finish this article by reminding us some of the benefits we get by embracing DI:

Dependency Injection Benefits — http://tutorials.jenkov.com/dependency-injection/dependency-injection-benefits.html

So if you want to know more, this is the next story to read: http://tutorials.jenkov.com/dependency-injection/dependency-injection-benefits.html

Thanks for reading, your feedback is gold!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.