node package manager
Share your code. npm Orgs help your team discover, share, and reuse code. Create a free org »



Ettore is a node.js IoC (Inversion Of Control) container built using coffee-script.

The principle of Ettore is of modularity and decoupling. To be exact, Ettore uses a more specific version of inversion of control namely - Service Locator. IMO A service locator provides a lot more flexibility then traditional form of dependency injection, both of which being a sub-varient of IoC.

Let's say you have the following class:

class Controller
    index: ->
        App.Posts.all (err, posts) ->
            # Retrieve all the posts from the database 
        @render 'posts'

Except from the mistake in this example (I'll get to that later), we are depending on a model and the whole database infrastructure to retrieve the posts, after which we use the data to render a page. The mistake I mentioned is that the @render method is not within the asynchrounous block. For the sake of this example it sits outside of it, but in a real-world example it would obviously be within. This is just for sake of simplicity as having it within the block / method adds another level of complexity.

The Problem:

The problem is that we are explicitly and staticly using a class and it's functionality. This is called a dependency, though we will always need dependencies, having them staticly written is a bad idea (I'll explain that later).

The Real Problem:

The real problem comes when testing this class. Let's pretend that we are testing the rendering functionality from a controller. Our example would fail as a decoupling example and would provide a bad testing environment. Why? Because we aren't just testing the rendering from within the controller, we are also testing the models and database infrastructure to some extend. When testing we want to "mock" the database or model and nullifying it, or to basically void it's functionality. People often use mocking or faking an object, sometime using both terms interchangably.

Our solution (IoC and Service Locator):

This library (if you want to call it that) provides an infrastructure to decouple all of your dependencies and effectively all your code.

We first must include and create a context object. This context object will manage any containers we set.

# file. 
# Create a new context object. 
Context = new (require('ettore').Context)
# Next, we want to create a new container object within the new context object. 
App = Context.create 'App'
# We now have a container object! 

A container object is the service locator and the IoC object. It contains all the functionality to decouple your code and manage your dependencies.

# Continuing from the previous code... 
# You can now set a new object using the container. 
App.set 'Controller''This object or key is actually just text now.'
App.get 'Controller'(err, Controller) ->
    if err then throw new Error "Some error."
    console.log Controller #  'This object or key is actually just text now.' 
#You don't actually have to use the async way at all: 
console.log App.get 'Controller' # 'This object or key is actually just text now.'