HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Designing a toy dependency injection library

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
toydesigningdependencylibraryinjection

Problem

Just for learning purpose I thought to write a simple and useful dependency injection service which would just do dependency injection but also it should expose its core too which would let the client code to do some advance stuffs.

I took inspiration from here but I think it does too much apart from that I think that the Factory and Provider thing can be done via calling resolve method in my library.

I need to know if I am missing something or can I improve my code to handle more cases which I don't know yet.

``
const RE = /^function\s[^\(]\(\s([^\)])\)/m;

const Color = {
RED: 'RED',
GREEN: 'GREEN',
BLUE: 'BLUE',
};

class Door {
constructor(color) {
this.color = color;
}

open() {
console.log('Kitchen door is open now!');
}
}

class Stove {
constructor() {
}

on() {
console.log('Gas stove is turned on!');
}

off() {
console.log('Gas stove is now off!');
}
}

class TeaMaker {
constructor(door, stove) {
this.door = door;
this.stove = stove;
}

makeTea() {
this.door.open();
this.stove.on();
console.log('Put water on stop');
this.stove.off();
console.log('Enjoying tea :)');
}
}

const injector = {
dependencies: {},
register: (key, value) => {
injector.dependencies[key] = value;
},
resolve: (deps, fn, scope={}) => {
let args = [];
for (let d of deps) {
if (injector.dependencies[d]) {
args.push(injector.dependencies[d]);
} else {
throw new Error(
Unkown Dep: ${d});
}
}

return () => {
return fn.call(scope, ...args, ...arguments);
};
},
get: (fn) => {
let deps = fn.toString().match(RE)[1].replace(/ /g, '').split(',');
let args = [];
for (let d of deps) {
if (injector.dependencies[d]) {
args.push(injector.dependencies[d]);
} else {
throw new Error(
Unkown Dep: ${d}`);
}
}
return new fn(...args);
}
};

injector.register('door', new Door(Color.RED));

Solution

In your injector you're exposing the dependencies object, in a way that all could access.

You should consider to hide it instead, so people will use just the API as it should be.

This happened because you choose to define your component just with a plain object approach.

If you want to write a lib or an utility, it is better to use one of the module pattern.

For example wrapping your code in a function if you mean to use it within a browser:

!function () {
    const dependencies = {};

    const injector = {
      // my code here
    };

    return injector;
 }()


Or with the node modules if you use in node:

const dependencies = {}

const injector = {
    // your code here..
}

export default injector


So you could expose just the API function you want.

This helps the developer to better understand how you design the lib to be used.

Code Snippets

!function () {
    const dependencies = {};

    const injector = {
      // my code here
    };

    return injector;
 }()
const dependencies = {}

const injector = {
    // your code here..
}

export default injector

Context

StackExchange Code Review Q#148070, answer score: 3

Revisions (0)

No revisions yet.