34

On the Wikipedia page on dependency injection, the disadvantages section tells us this:

Dependency injection increases coupling by requiring the user of a subsystem to provide for the needs of that subsystem.

with a link to an article against dependency injection.

Dependency injection makes a class use the interface instead of the concrete implementation. That should result in decreased coupling, no?

What am I missing? How is dependency injection increasing coupling between classes?

yoozer8
  • 693
  • 1
  • 8
  • 20
BЈовић
  • 13,981
  • 8
  • 61
  • 81
  • 2
    I'm not sure who wrote that list of disadvantages, but I'd take it with a grain of salt. For example, I've seen DI reduce the size of a code base by 2/3 by eliminating a ton of redundant set-up code. – sea-rob Jun 04 '14 at 14:53
  • @RobY I mostly used factory to inject the dependency, and my experience is that it increases the code size, but simplifies testing. – BЈовић Jun 04 '14 at 15:22
  • Try using an alternative like Registry or Context Passing ;) Or else code that just instantiates objects and then pulls their properties from config. Mainly, I'm talking about the difference between now and 15 years ago. – sea-rob Jun 04 '14 at 15:24
  • Related: https://stackoverflow.com/a/9503612/264697. Mark Seemann's answer explains how overall coupling is reduced using Dependency Injection. – Steven Nov 21 '14 at 12:07

3 Answers3

45

So, what am I missing?

Dependency Injection decreases coupling between a class and its dependency. But it increases the coupling between a class and its consumer (since the consumer needs more info to create it) and the dependency and its consumer (since the consumer needs to know the dependency to use).

Very often, this is a good trade off. The class shouldn't know the details about its dependencies beyond an interface, and it should be the responsibility of the application to tie specific bits of code together.

Telastyn
  • 108,850
  • 29
  • 239
  • 365
23

Suppose you have a subsystem S that depends on a database connection D. Without dependency injection, there is a relatively tight coupling between S and D, because S needs to know both how to use D and how to create it. The rest of the system, however, can be blissfully unaware of this dependency between S and D.

With dependency injection, the coupling between S and D becomes looser, because you remove from S the knowledge how to create a D. S just needs to know how to use it. The increased overall coupling comes from the fact that other parts of the system now need to know about D and possibly how to create one. The extent of this increase in coupling depends on how the dependency on D gets injected into S:

  • With constructor injection the creator of S needs a dependency on D and possibly the knowledge how to create one.
  • With method-level injection, each caller of a method of S through which a D gets injected needs a dependency on D and possibly the knowledge how to create one.

In either case, the number of classes that depends on D increases and the knowledge how to create a D still needs to be present somewhere in the system. This creates an overall increase of coupling.

Bart van Ingen Schenau
  • 71,712
  • 20
  • 110
  • 179
  • Ok, it makes sense for constructor and setter injection. But if one uses factory or strategy pattern, the creation is moved there, and class only uses the injected object. Or, is that not a dependency injection (only inversion of control)? – BЈовић Jun 04 '14 at 14:46
  • Even with factory injection, the creator of `S` needs to supply a factory of `D`, which means it needs to know that `S` uses `D`(or at least some interface of it). – Idan Arye Jun 04 '14 at 18:55
7

I strongly disagree that it increases coupling.

Without dependency injection you have tight coupling between a sub system and the concrete implementation of the dependency.

With dependency injection you have decoupled the sub system from the implementation of the dependency.

Making the argument that it increases coupling between the consumer and this sub system is VERY questionable as it implies that the consumer is now tightly coupled to the dependency required by the sub system. All it means is you are writing tightly coupled code that couples your consumer to the dependency. Ideally ALL your code is decoupled.

Constructor Injection:

Dependency resolution is handled by a dependency injection container or a factory. The consumer can get a concrete implementation of the sub system from the dependency injection container or a factory.

The consumer does not need to know what the constructor of the sub system even looks like. There is no coupling to the sub system dependency.

Method Injection:

Same as constructor injection except that now the consumer needs to get a concrete instance of the dependency from the container or factory (or even have it method/constructor injected) and inject it into the method. Again, the consumer is not coupled to a concrete implementation of the dependency.

TL;DR Worst case for dependency injection in a sub system is that the coupling is shifted to consumer code. THERE IS NO OVERALL INCREASE IN COUPLING.

Best case is that all systems are now loosely coupled and dependency injection is controlled through dependency injection containers or factories.

Hawk
  • 181
  • 4