Dependency Injection in Node.js made easy with “Box”
In a nutshell, Dependency injection (DI for short) is a fancy term for a software design pattern in which the dependencies (or packages, services) are injected into the dependent object. It basically allows the creation of dependencies outside of the service and provide those objects to the dependent object.
Dependency Injection helps in decoupling of our modules which makes it easier to maintain better codebase. Manual DI kind of sucks to both, implement and maintain. So, I’m demonstrating how to use Haluka Box to make DI look awesome and useful.
To demonstrate the use of Box, let’s use the world’s favorite project “Todo List” project. (I know you might be thinking another cliché Todo list project, but trust me, Box is gonna make everything look awesome).
GitHub Repo for the project — https://github.com/hacktivistic/box-todo
Let’s start with the Todo Service —
Todo.js
Todo Service is just a ES6 class service having CRUD (create, retrieve, update, delete) methods to handle the Todo. Nothing special is going on here — It just uses Database to perform the respective operations. It also requires a User object so that a Todo can be mapped to a specific user.
In the above code, Database and User are the two dependencies of Todo. In normal cases, you would just create those objects and pass them into the Todo. But, with Box, we’ll do things a bit differently ;)
Now, let’s see Database — It’s just a sample in-memory array storage just for the sake of demonstration.
Database.js
Here, the Database has nothing out of the ordinary going on. We have a “dataRepo” array which acts as a in-memory data store and Database has bunch of methods, executing Array functions for storing, searching, updating and removing the stored values.
Packing Things Together
Now, that we have our dependent and dependency ready, let’s use Box to make our life easier. Back to our Todo Project, we’ll now install required modules for our awesome project.
npm install @haluka/box express
Box exposes a Container class which is what we’ll be using here. It can be initialized into the project as —
const { Container } = require('@haluka/box')
Let’s set up our Box Container and register all our services into it.
box.js
Registration of the services looks good. It isn’t that of a tough task to register all of the services. Even if y.ou have 100s of services, Box has plans to automatically register them for you. [See CHANGELOG for upcoming features.]
Now that everything is ready, let’s configure our Server with express
. Since express is already registered into Box as http
. We can just call, h.http
to get the express app instance. Pretty handy, isn’t it.
index.js
Okay, I guess this was pretty much self explanatory. Remember we had exposed box
through the middleware? Yes, we use that box
from the req
to resolve our dependencies in our routes.
Here, since logged user is not registered, the fallback user specified in opts
is used. If you have implemented a session, you may register the logged user from session in middleware or pass it as a resolving option by using resolve
method. For Example —
req.box.resolve('Todo', { User: req.session.user })
// pretty handy if you want to override fallback options or registered provider.
We can clearly see the benefit of using Box. We didn’t have to worry out the database or logged user in this case.
It is also easier to replace Database implementation in our app. We just need o use another Database provider like, RethinkDB or MongoDB, and setup the Database Service implementing the same interface and register it into the Database
provide. With almost little to no changes in the Todo Service, we’ll be able to completely change the database provider.
This usually comes in handy if you have multiple environments on which your application is running. Based on the current environment, you can register different implementations of Database.
Conclusion
Dependency Injection is observed in many of our applications and usually is done manually, but to make it look better Box can be used. Due to the decoupling of the services, our services are framework independent so they can be used anywhere it could be stuffed with any framework. That’s what’s called a beautiful code.
Working code is good, beautiful code is best.
GitHub Repo for the project — https://github.com/hacktivistic/box-todo