The Node.js way - DI vs Module Require?!

imthedeveloper

ImTheDeveloper

Posted on November 20, 2017

The Node.js way - DI vs Module Require?!

Dependency Injection vs Module Requiring

Since picking up a pet project and digging back through all of my old Javascript projects to remember how exactly this thing works I've uncovered a slightly deeper understanding which inevitably has led to confusion, questioning and plenty of reading.

The topic today is dependency injection vs requiring modules, which if I were working day to day with other developers I could easily find answered. Alas I have had to go to the various remote resources like Stackexchange, Medium, RisingStack and trusty Google, where more often than not I am met with out of date examples, biased views from 10 years ago and some nice flame wars around why the originators question is wrong from the start. I'm here to seek enlightenment from a community that is open to discussion.

TLDR; What is the preferred mechanism for pulling in dependencies from other modules within others.

My current project I have found that my "app.js" main file requires in a bunch of modules in order to knit together the hand off to lower down functionality which has dependencies on those top level modules. Typically this could be (I've simplified this massively):

const MQTTClient = require('./mqtt')
const Router = require('./router')
const client = MQTTClient .start('hostname')

const messageRouter = Router.init(client,{options})

client.on('message',messageRouter.handleMessage(topic, payload))

This means within the router I can always access the client methods and properties assigned from MQTT. I've found many posts suggesting this is good, I've found many posts suggesting this is bad. Ultimately though here are my impressions:

  • This is potentially not even DI, to me this feels like I'm just passing a function which is an object as a parameter.
  • Node/Javascript will cache the required module, so re-requiring it throughout my project is just referencing that cache.
  • Testing within Router has been hugely easy. I find that creating a fake client object results in greater control over my tests.
  • Functionally, there would have been no difference if the require MQTT sat within Router.js rather than my App main file, but the "single route in" to my App seems to be easier to understand.
  • I dislike seeing a lot of "required" modules scattered around my project but at the same time, tracing back through function input and outputs to find the root of the injection could become time consuming on a large project.
  • Javascript is not like other languages that rely heavily on DI. Module requiring is effectively another method of bringing objects into the scope you need.
  • There seems to be a lot of DI JS libraries being produced and in fact you see these injections occurring in Express, Angular, Hapi etc all the time.
  • People comment a lot about using a factory instead.

Thoughts and opinions?

💖 💪 🙅 🚩
imthedeveloper
ImTheDeveloper

Posted on November 20, 2017

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related