0

I'm trying, as a test, to create Dependency Injection from scratch in JavaScript. Consider the following code structure, which outputs an Alert:

  • Does it satisfy the terms of the Dependency Inversion Principle?
  • Is it technically Dependency Injection?
  • and if not, what structural changes are necessary?

-

function App(name, services, clients) {
    var that = this;
    this.name = name;
    this.services = services || {};
    this.clients = clients || {};
    this.Service = function (func) {
        func();
    }
    this.Client = function () {
        this.dependencies = {};
        for (var i = 0; i < arguments.length; i++) {
            if (that.services[arguments[i]]) {
                this.dependencies[arguments[i]] = that.services[arguments[i]];
            }
        }
    }
}

var fooBar = new App('fooBar');
fooBar.services.alert = new fooBar.Service(function() {
    alert('Yep!');
});
fooBar.clients.alerter = new fooBar.Client('alert');
fooBar.clients.alerter.alert();

One of the structural aspects of this structure that I'm not sure about is the fact that in the above code, the client's constructor knows about the code to inject dependencies.

Wikipedia says:

Passing the service to the client, rather than allowing a client to build or find the service, is the fundamental requirement of the pattern. The client is not allowed to call the injector code.

However, an answer on this site explaining the naming of dependency injection mentions the constructor can inject the dependency:

Let's say you have some sort of "repository" class, and that repository is responsible for handing data to you from a data source.

The repository could establish a connection to the data source by itself. But what if it allowed you to pass in a connection to the data source through the repository's constructor?

Note, the above is shortened (working) code, I omitted code involved in defining services in order to make the code sample simpler (also omitted strict error handling in case of a missing dependency) - the overall structure should be apparently correct or incorrect - that's the focus of the question, not the specific implementation.

J.Todd
  • 3,833
  • 5
  • 22
  • 27
  • Note, I'm not asking about improvement (which would be off-topic) but just about fundamental issues/changes necessary in the structure or syntax. – J.Todd Sep 26 '15 at 11:19
  • is it even possible to do DI without type safety? – Ewan Sep 26 '15 at 12:22
  • 1
    Possible? or wise? – Charles Merriam Sep 26 '15 at 17:19
  • @Ewan this is just minimal code, to get the structure across. I will add features but first I'm checking whether or not the structure is in fact Dependency Injection. I *think* there's a structure issue since the `Client` handles the dependency gathering, but I haven't been able to figure out how to make a separate component inject the dependencies in a way that makes any sense. – J.Todd Sep 26 '15 at 19:18
  • @CharlesMerriam and is type safety even viable in a loosely typed language? – J.Todd Sep 26 '15 at 20:20
  • FWIW, AngularJS's dependency injection mechanism is widely regarded as state-of-the-art. You can learn more about it [here](https://en.wikipedia.org/wiki/Dependency_injection#AngularJS_example), [here](https://docs.angularjs.org/guide/di), and [here](http://www.tutorialspoint.com/angularjs/angularjs_dependency_injection.htm). – Robert Harvey Sep 27 '15 at 00:46
  • @RobertHarvey thanks. That angular implementation is so advanced, it'd be very hard for someone not yet a guru such as myself to look into the source and understand the structure for actually producing DI. That's why I'm asking about the structure of an extremely simple implementation for the purpose of learning through experience. – J.Todd Sep 27 '15 at 02:00
  • @JonathanTodd I didn't mean it as a comment on your code. Just whatever method you choose to inject your dependency, how do you enforce that the dependency meets the requirements, ie having an alert method on it – Ewan Sep 27 '15 at 10:16
  • @Ewan Ohh, I see.. – J.Todd Sep 27 '15 at 15:05
  • The simplest form of DI is simply "Handing dependencies to an object through its constructor." – Robert Harvey Sep 27 '15 at 19:50
  • @RobertHarvey I thought that was the case! Is my comment on the answer below accurate then? Is that answer partially incorrect or misleading? – J.Todd Sep 27 '15 at 19:52
  • 1
    Jules is referring to a DI container. But you don't need a DI container to do DI. DI containers just allow you to wire up all of the object dependencies automagically. The constructor is not the injector; the object or method that is calling the constructor is the injector. – Robert Harvey Sep 27 '15 at 19:59

1 Answers1

2

I'm not quite sure what your code is doing, but I'm pretty sure it's not something I'd recognise as dependency injection. Specifically, it seems as though your client object is responsible for finding its dependencies from a central repository during construction (albeit using a dependency name that's phased as a constructor parameter), which strikes me as closer to the Service Locator pattern than Dependency Injection.

Jules
  • 17,614
  • 2
  • 33
  • 63
  • Hold on, the *constructor* isn't actually the client though. I just read something in the Wikipedia article which which says the constructor can be the injector: The injector may be referred to by other names such as: assembler, provider, container, factory, builder, spring, **construction code**, or main. – J.Todd Sep 27 '15 at 16:40
  • I don't think that means the usual object-oriented concept of a constructor, but rather a dedicated section of code with the responsibility of creating all the long-lived objects in the system. – Jules Sep 27 '15 at 17:28