Thoughts on JavaScript IoC containers with Require.js & TypeScript

Lately I’ve been thinking about IoC in JavaScript and I would like to find out the community opinion about my thoughts…

The require.js documentation recommends avoiding the usage of named modules and to let the naming task to the optimization tool:

It is normally best to avoid coding in a name for the module and just let the optimization tool burn in the module names. The optimization tool needs to add the names so that more than one module can be bundled in a file, to allow for faster loading in the browser.

I understand that by using unnamed modules we must provide the relative path of the module and the path will help us to locate the dependencies of a particular module.

requirejs.config({
    baseUrl: './'
});

define(['models/user_service'], function(userService){
    var users = userService.get();
});

In the example above, the usage of unnamed modules helps us to know where is located the dependency userService.

We have a dependency which is declared by the usage a relative path. The problem is that if, for example, we move the file from ./models/user_service.js to ./services/user_service.js we will have to search for that relative path in all the modules and update it.

In the other hand, if we use named modules, the paths will be maybe less accessible but we will know that all the paths will be located in the require.js configuration:

requirejs.config({
    baseUrl: './',
    paths: { 
        // All our module paths will be located here
        userService: './models/user_service'
    }
});

Using named dependencies will avoid the usage of relative paths in modules and if we move files around, we will only have to change the paths once on the require.js configuration.

define(['userService'], function(userService){
    var users = userService.get();
});

If we change the module name we would still have a problem because we are not depending on an abstraction (interface).

When we use named modules the require.js configuration feels like the applications’s composition root and that is a good thing from my personal point of view.

Unfortunately we don’t have an IoC container or interfaces in JavaScript to make this a real inversion of control implementation.

I don’t think we should try to add interface emulation to JavaScript, I have seen some attempts of implementing IoC containers in JavaScript and they force you to declare interfaces in a horrible manner:

export class IITodoService implements IInterfaceChecker {
    className: string = 'IITodoService';
    methodNames: string[] = ['loadMTodoArray', 'storeMTodoArray'];
};

Also, emulating interface behavior at run-time will probably not be a good idea for the applications performance. But I like the TypeScript idea of adding interface support only at compilation time. So I thought that now that we have a composition root for our application, we could use TypeScript to declare our module interfaces and maybe fork require.js to add support for something like the following:

requirejs.config({
    baseUrl: './',
    paths: {
        { 
           bind: 'IUserService',
           to : 'UserService', 
           path : './models/user_service' 
       }
    }
});

define(['IUserService'], function(userService){
    var users = userService.get();
});

The idea is that everything will work just like before at run-time but during the development and compilation time TypeScript will check that our modules implement an interface and we will be then able to follow the dependency inversion principle:

Depend upon Abstractions. Do not depend upon concretions

Please let me know your thoughts at @OweR_ReLoaDeD.

 Update

I decided to create my own IoC container for TypeScript apps, you can learn more about it at:

 
38
Kudos
 
38
Kudos

Now read this

Writing JavaScript APIs

This article covers the most important things that you will need to consider before and while writing your own utilities and libraries. We’ll focus on how to make your code accessible to other developers. A couple of topics will be... Continue →

Subscribe to Wolk Software Engineering

Don’t worry; we hate spam with a passion.
You can unsubscribe with one click.

q2NNL8JA24VR4bZAnG9S