views:

443

answers:

5

I find that my constructors are starting to look like this:

public MyClass(Container con, SomeClass1 obj1, SomeClass2, obj2.... )

with ever increasing parameter list. Since "Container" is my dependency injection container, why can't I just do this:

public MyClass(Container con)

for every class? What are the downsides? If I do this, it feels like I'm using a glorified static. Please share your thoughts on IoC and Dependency Injection madness.

Thanks in advance.

-JP

+19  A: 

You are right that if you use the container as a Service Locator, it's more or less a glorified static factory. For lots of reasons I consider this an anti-pattern.

One of the wonderful benefits of Constructor Injection is that it makes violations of the Single Responsibility Principle glaringly obvious.

When that happens, it's time to refactor to Aggregate Services. In short, create a new, more coarse-grained interface that hides the interaction between some or all of the fine-grained dependencies you currently require.

Mark Seemann
+1 for quantifying the refactoring effort into a single concept; awesome :)
Ryan Emerle
for real? you just created an indirection to move those parameters into another class, but they are still there! just more complicated to deal with them.
irreputable
+1 for mentioning it is an anti-pattern.
fastcodejava
@irreputable: In the degenerate case where we move *all* dependencies into an Aggregate Service I agree that it's just another level of indirection that carries no benefit, so my choice of words were slightly off. However, the point is that we move only *some* of the fine-grained dependencies into an Aggregate Service. This limits the number of dependency permutations both in the new Aggregate Service and for the dependencies left behind. This makes both simpler to deal with.
Mark Seemann
The best remark: "One of the wonderful benefits of Constructor Injection is that it makes violations of the Single Responsibility Principle glaringly obvious."
Igor Popov
+4  A: 

I don't think your class constructors should have a reference to your IOC container period. This represents an unnecessary dependency between your class and the container (the type of dependency IOC is trying to avoid!).

derivation
+1  A: 

dependency injection is a hell'v drug. in a few years people will wake up and feel deeply embarrassed that there were so gullible.

irreputable
+1  A: 

The difficulty of passing in the parameters is not the problem. The problem is that your class is doing too much, and should be broken down more.

Dependency Injection can act as an early warning for classes getting too big, specifically because of the increasing pain of passing in all of the dependencies.

kyoryu
+1  A: 

What dependency injection framework are you using? Have you tried using setter based injection instead?

The benefit for constructor based injection is that it looks natural for Java programmers who don't use DI frameworks. You need 5 things to initialize a class then you have 5 arguments for your constructor. The downside is what you have noticed, it gets unwieldy when you have lots of dependencies.

With Spring you could pass the required values with setters instead and you could use @required annotations to enforce that they are injected. The downside is that you need to move the initialization code from the constructor to another method and have Spring call that after all the dependencies are injected by marking it with @PostConstruct. I'm not sure about other frameworks but I assume they do something similar.

Both ways work, its a matter of preference.

David W Crook