Symptoms
Classes that depend on the container.
Consider the following example. We have a class BImpl that requires an A instance. It declares the dependency on the container so it can look up that A:
public interface A { } public class AImpl implements A { } public class BImpl implements B { private final A a; BImpl(PicoContainer pico) { a = (A) pico.getComponentInstanceOfType(A.class); /* alternatively: a = (A) pico.getComponentInstance("a"); */ } }
It can be used in the following way:
MutablePicoContainer pico = new DefaultPicoContainer(); pico.registerComponentImplementation("a", AImpl.class); pico.registerComponentImplementation("b", BImpl.class); pico.registerComponentInstance(pico); ... B b = (B) pico.getComponentInstance("b");
This will work, but it's an antipattern.
The reasons why the above implementation of BImpl is an antipattern are:
- It introduces an unneeded dependency from BImpl to the container.
- This makes BImpl hard to test without a container.
- B assumes that the container has a registered an A. As a result, B won't FailFast if it hasn't. Instead, a will reference null, and BImpl will FailLate.
Causes
Not sure. Poor understanding of how PicoContainer works? Not being able to think "simple"?
What to do
The simple and elegant solution to this antipattern is not to complicate the world more than it is.
Here is how it should be:
public class BImpl implements B { private final A a; BImpl(A a) { this.a = a; } }
PicoContainer will figure out that BImpl needs an A instance, and will pass in the AImpl, as this is an implementation of A.

Comments (2)
Apr 01, 2005
Maksym Kovalenko says:
While I agree with this antipattern, I'd like the following question to be answe...While I agree with this antipattern, I'd like the following question to be answered. Assume that you have not a trivial example like here but a real project. Hierarchy of component might be quite big. Let's say you have a component 20 level deep relative to root component. This root component was instantiated by some bootstrap class that configured PicoContainer properly.
Now what if my nested component needs additional dependency, that is addition constructor parameter new to the project? If I will try to avoid antipattern I will need to propagate this parameter from to bottom to the top. And this might be quite frustrating at top-level component to see constructor parameters that neither this class nor classes it immediately depend on ever need.
My guess that some kind of Service Locator (PicoContainer might be considered as one) could be quite useful as it is much easier to pass one parameter to class constructor instead of passing tens of them and propagate or delete them from class hierarchy as nested components change. But this is kind of against whole dependency injection philosophy where you get only what you need...
Apr 01, 2005
Aslak Hellesøy says:
If some class needs to be modified to accomodate for an additional dependency, y...If some class needs to be modified to accomodate for an additional dependency, you just declare another constructor parameter in that class.
As long as you have registered all classes your system requires in your PicoContainer, all dependencies will be injected by PicoContainer.
I don't understand what you mean by propagating parameters from the bottom to the top.
I'm not sure I understand your problem. Perhaps you could illustrate with some code? Feel free to ask on the mailing list too.