Should You Use Dependency Injection in JavaScript?
By: David Fekke
Tags: JavaScript, Programming, Coding, Software Development, Dependency Injection

Originally published at https://fek.io.

Please subscribe to the Polyglot Engineer Channel

I have seen some posts on JavaScript and for other languages that dissuade the use of Dependency Injection. I even had a boss at one company I worked for tell his developers that we should never use Dependency Injection.

Dependency Injection (DI), sometimes referred to as ‘Inversion of Control’, is when an object receives other objects or functions it depends on for part of its functionality. This can be achieved by passing an object through object instantiation with a constructor or with a property setting. This is very common in the world of statically typed languages like Java or C#. There are many popular frameworks built specifically for managing dependencies in the statically typed object-oriented world.

DI allows specific functionality to be loaded at runtime. One of the advantages of being able to change the functionality of an object at runtime is to provide greater flexibility and make our applications more loosely coupled. A very common use case is using mocking during testing. There are some great libraries in Node.js like Sinon that make mocking very easy, but we can accomplish the same task by using DI.

Testing scenario

It is very common with testing to substitute code that communicates with a database or a network request with a mock or fake. This is because in a lot of CI/CD workflows the build or testing server may not have access to a database server or a network needed for the actual service. This is an excellent use case for DI to substitute an actual service with a mock or fake service.

There are many different reasons to use DI, but testing is one of the most common reasons.

Poor Mans DI

I have a technique that I have used throughout the years for configuring DI in my applications whether they are statically typed or duck-typed like JavaScript that I like to call ‘Poor Mans Dependency Injection’. With this technique, I usually create default dependent objects if a required object is not passed in on object instantiation.

Lets’ say we have a cart object that needs to calculate a tax rate for a certain location. In a lot of e-commerce systems that kind of data has to be calculated based on the location of the user, with the sales tax being different for every location. We can create a factory function that creates a shopping cart with an injectable function for calculating the tax.

If we look at the following example, we are creating an object with functions for adding items to the cart and calculating the totals and subtotals. We have a function that we can pass into our settings constructor object called taxrepository . We will use this function to calculate our taxes.

Lets’ create a test function for calculating our taxes. We will make this a pure function without any side effects.

function calculateMyTax(subtotal) {

return subtotal * 0.11;

}

When we instantiate this object with our factory function, we can just pass it into our settings object;

We can now get the subtotal and calculate the taxes.

Defaulting Behavior

All of the objects that I define, I try to create defaults for whenever an injectable behavior is not included in the constructor. That way if someone is using my object without passing in the needed objects, it will either get an error or a default function if it is missing from the constructor. We can modify the factory function to use a default if no taxrepository is passed in the settings object.

We also might want to have our factory function fail if the developer calling our function forgets to pass the taxrepository into the constructor.

Dependency Injection Frameworks

DI frameworks are extremely popular in the statically typed object-oriented world of Java and .NET development, but there are DI frameworks you can use for JavaScript. One of the frameworks is called di4js, and will work with either Node.js or plain old JavaScript in the browser. Here is an example from the di4js readme;

This example is from the di4js Github repo

Conclusion

Dependency Injection is a very powerful tool for configuring an application to use certain dependencies when creating objects. Whether you are using a “poor man's” Dependency Injection or a full-fledged DI framework, it can be a very useful tool for configuring different behavior in an application.

More content at plainenglish.io