Why InversifyJS

There are many good reasons to use InversifyJS but we would like to highlight some of them:

1. Real decoupling

InversifyJS offers you real decoupling. Consider the following class:

let TYPES = {
  Ninja: Symbol.for("Ninja"),
  Katana: Symbol.for("Katana"),
  Shuriken: Symbol.for("Shuriken")
};

export { TYPES };
import { TYPES } from "./constants/types";

@injectable()
class Ninja implements Ninja {

    private _katana: Katana;
    private _shuriken: Shuriken;

    public constructor(
        @inject(TYPES.Katana) katana: Katana,
        @inject(TYPES.Shuriken) shuriken: Shuriken
    ) {
        this._katana = katana;
        this._shuriken = shuriken;
    }

    public fight() { return this._katana.hit(); };
    public sneak() { return this._shuriken.throw(); };

}

The Ninja class will never point to the Katana or Shuriken classes. However, it will point to the interfaces (at design-time) or Symbols (at run-time) which is admissible because these are abstractions and depending upon abstractions is what DI is all about.

The InversifyJS container is the only element in the application aware of the life-cycle and dependencies. We recommend to do this in a file named inversify.config.ts and store the file in the root folder that contains the application source code:

import { TYPES } from "./constants/types";
import { Katana } from "./entitites/katana";
import { Shuriken } from "./entitites/shuriken";
import { Ninja } from "./entitites/ninja";

container.bind<Katana>(TYPES.KATANA).to(Katana);
container.bind<Shuriken>(TYPES.SHURIKEN).to(Shuriken);
container.bind<Ninja>(TYPES.NINJA).to(Ninja);

This means that all the coupling in your application takes place in one unique place: the inversify.config.ts file. This is really important and we are going to prove it with an example. Let's imagine that we are changing the difficulty in a game. We just need to go to the inversify.config.ts and change the Katana binding:

import { Katana } from "./entitites/SharpKatana";

if(difficulty === "hard") {
    container.bind<Katana>(TYPES.KATANA).to(SharpKatana);
} else {
    container.bind<Katana>(TYPES.KATANA).to(Katana);
}

You don't need to change the Ninja file!

The price to pay is the usage of Symbols or string literals but this price can be mitigated if you declare all your string literals in a file which contains constants (like actions in Redux). The good news is that in the future the symbols or string literals could end up being generated by the TS compiler, but that is in the hands of the TC39 committee for the moment.

2. Solves competitors issues

Some "old" JavaScript IoC container like the angular 1.x $injector have some problems:

Source

InversifyJS solves these problems:

  • There is support for transient and singleton scope.
  • There are no namespace collisions thanks to tagged, named and contextual bindings.
  • It is a stand alone library.

3. All the features that you may need

As far as I know it is the only IoC container for JavaScript that features complex dependency resolution (e.g. contextual bindings), multiple scopes (transient, singleton) and many other features. On top of that there is room for growth with features like interception or web worker scope. We also have plans for the development of dev-tools like browser extensions and middleware (logging, caching...).

4. Object composition is a pain

You may think that you don't need an IoC container.

If the preceding argument is not enough you may want to read the following:

5. Type safety

The library has been developed using TypeScript so type safety comes out of the box if you work with TypeScript but it is nice to mention that if you try to inject a Katana into a class that expects an implementation of Shuriken you will get a compilation error.

6. Great development experience

We are working hard to provide you with a great IoC container for your JavaScript apps but also a great development experience. We have spend a lot of time trying to make the InversifyJS as user friendly as possible and are working on development tools for chrome and we have already developed a logger middleware to help you to debug in Node.js.

results matching ""

    No results matching ""