I'm trying to employ SOLID principles learnt from strongly-typed languages in a Node.js application, and implement dependency injection through the constructor in my modules.
Without a compiler to help me, I've found myself impulsively writing type-checking and null-reference checking logic to make sure dependencies of the correct type are being passed in.
var _ = require('lodash');
var ExampleModule = function(dependencies) {
var app, express, http;
if(_.isUndefined(dependencies) || typeof dependencies !== 'object') {
throw new ReferenceError('No dependencies object passed to the constructor. Actually passed: ' + typeof dependencies);
}
if(_.isUndefined(dependencies.express)) {
throw new ReferenceError('The express module must be passed as the \'express\' property in the constructor.');
} else {
express = dependencies.express;
}
// Tempted to add a type check for dependencies.express here
if(_.isUndefined(dependencies.http)) {
throw new ReferenceError('The node http module must be passed as the \'http\' property in the constructor.');
} else {
http = dependencies.http;
}
// Tempted to add a type check for dependencies.http here
};
module.exports = ExampleModule;
This feels fundamentally wrong for two reasons
I don't want to spend half my time maintaining type-checking logic, but I also don't want to spend half my time debugging errors when the wrong type of a dependency is passed in.
What design pattern am I missing that would solve this problem?
small, but important clarification: the SOLID "D" is not dependency injection. it is dependency inversion.
for a better understanding of SOLID as it pertains to dynamically typed languages, watch this presentation from Jim Weirich: http://confreaks.tv/videos/rubyconf2009-solid-ruby
it's about Ruby, but all the principles are the same when applied to JavaScript.
there's also my own SOLID JavaScript presentation I did a few years ago: https://sub.watchmecode.net/episode/solid-javascript-presentation/
...
your own answer talks about require
as dependency injection, but this isn't correct.
the require
call is a module loader, not a dependency manager. the difference is subtle, but important.
the call to require
only loads code from another file. it does not supply the dependency to your other code. you have to either call the code w/ the loaded module, or use another tool such as wire.js to supply the dependency for you.
...
regarding your dependency injection question: "it depends" is the only viable answer.
i rarely use type checking like this, when dealing with the internals of my applications.
however, if you're building an API that is called from third parties, it is often necessary to do what you have done, to make sure the API is called correctly.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments