Dependency Injection: a discussion of the pros and cons

It’s tricky because the article rambles and rants, but below are a few of the criticisms I could distill. I’ll start with what seemed like the better criticism, then it’s downhill from there.

  • “Here you see that the dependent object is created within the constructor of its consumer, although the dependent is not actually accessed until later (if at all). I personally do not like this method as it is possible to create an object which is not actually used, which could lead to performance issues.”

The issue is what happens when we’re dealing with an expensive object. For example, it’s common in web development to do something like this:

if ($form->isValid()) {
    // save to db
} else {
    // render form with errors
}

Connecting to a database can be expensive. Ideally, we want to do it only when the condition evaluates to true. If we’re using a service locator, then it’s admittedly straightforward:

if ($form->isValid()) {
    $db = $container->get('database');
    // ...
} else {
    // render form with errors
}

If instead we were using DI, the way we would solve this is with the proxy pattern. That is, an object that serves as a placeholder for the real object to defer its creation until we actually need it (aka lazy load).

So which is best? It can vary from one scenario to another. A (web) MVC controller is certainly a good candidate for SL rather than DI, which is probably why most (all?) frameworks do it that way. But in other scenarios, I’d wager that DI would be the better option most of the time.

It’s a good topic for a nuanced article, not an “is evil” rant. :wink:

  • “What happens if the constructor of the dependent requires arguments which are not available until the consumer is just about to communicate with that dependent?”

In this case, the consumer isn’t a consumer at all. It’s a factory. That is, the consumer doesn’t need an instance; it creates an instance. If, after it’s been created, we proceed to do other work that uses that new instance, then chances are good those two tasks should be separated, since they have distinct responsibilities.

  • “If you build in, at great expense, the ability to make certain changes in your application architecture, but those changes are rarely made, then surely you are violating the YAGNI principle?”

The key factor, of course, is whether changes are rarely made. Once upon a time, we tried to do all the analysis and design up front. Think waterfall. But as it turns out, requirements change all the time, and therefore software changes all the time. Today, an important factor that makes an architecture good or bad is how adaptable it is to change.

  • “This “solution” is supposed to address the problem of dependencies, but what exactly is the problem? You cannot eliminate dependencies altogether as your software just would not work.”

This criticism misunderstands DI altogether. DI doesn’t try to eliminate dependencies. It changes (inverts) how you get them and who creates them.

2 Likes