One of the great things about dependency injection is that a class's dependencies are explicitly defined in its interface (ie constructor). If a dependency injection container is used, however, many of these dependencies are consolidated into one dependency (the container). Therefore, many of a class's true dependencies are hidden behind the container. How is this avoided so that dependencies are still explitly defined while using a dependency injection container?
-
1No class which consistently uses constructor injection depends on a DI Container. You *may* use a container to wire up such classes, but then again you don't have to. How is that not explicit enough? – Mark Seemann Mar 18 '12 at 08:15
-
If class A is constructed using a DI container, and A has-a B, and B has-a C, then how does C access its needed dependencies? How do classes a few levels down the call stack access deendencies? – orourkedd Mar 18 '12 at 16:10
-
They use Constructor Injection as well. So if C depends on D, it gets it through its constructor. – Mark Seemann Mar 18 '12 at 17:21
-
So all of my classes should have constructors like: __construct(DatabaseAdapter $db, Cache $cache, Logger $logger, ...) ? – orourkedd Mar 19 '12 at 05:36
-
Yes and no: they most likely shouldn't depend on cache, logger and other cross-cutting concerns: http://stackoverflow.com/questions/1708992/what-are-the-different-methods-for-injecting-cross-cutting-concerns/1709048#1709048 http://stackoverflow.com/questions/8426132/consolidating-asp-net-mvc-controller-dependencies-structuremap/8427915#8427915 – Mark Seemann Mar 19 '12 at 07:12
-
@MarkSeemann, thanks for the great input. I checked out your blog and am looking forward to doing some reading! Question: Zend uses "optional dependencies" (I dont know what they're really called)where the constructor takes requires deps, and setter functions are used for optionally setting loggers, caching and oher cross cutting concerns. Is this a good way to implement these cross-cutting concerns? – orourkedd Mar 19 '12 at 15:26
-
Cross-cutting concerns aren't 'optional' - they are *cross-cutting*. A service shouldn't know anything about them. They should wrap around the service. So with the caveat that I don't know Zend I don't think 'optional dependencies' sound like a good fit. – Mark Seemann Mar 19 '12 at 16:46
-
@MarkSeemann So letting a container like EJB injecting a dependency in its way (`@EJB FxRatesService fxRatesService;`) has no redemption in terms of making dependencies explicit? I mean, if you want explicit dependency you shouldn't use this kind of dependency injection? – Caffé Sep 26 '14 at 14:23
-
@Caffé With the caveat that I don't know EJB either, how does the `@EJB` attribute make anything more explicit? Just by looking at the constructor argument list, you can see what the class *needs*. Is anything else required? Doesn't the `@EJB` attribute only increase coupling? – Mark Seemann Sep 26 '14 at 14:36
-
@MarkSeemann In the code I showed, the `@EJB` is there to inject a dependency in an object instantiated by the Server Application, and the server doesn't care about the constructor (actually, it requires a parameterless constructor). Maybe if we could tell the server to look at the constructor to know what needs to be injected, so we could use the same constructor in the tests and in the production environment and would never have to look the code inside to realize the class dependencies. Unfortunately we can't. Well, it would be a long conversation. Thanks anyway. – Caffé Sep 26 '14 at 15:44
-
wow, I just read this question that I asked 3 years ago and I can't believe how much I've grown since then! – orourkedd Sep 26 '14 at 19:56
-
@Caffé If I understand you correctly, this sounds like a limitation in the framework you're using. FWIW, most .NET frameworks worked like that 5 years ago, but these days, you can redefine how the server wires up objects. – Mark Seemann Sep 27 '14 at 07:43
3 Answers
Yes and no, it really depends on how you dependency injection container works.
I don't see any problem with this kind of code:
class Class1 {
/**
* @Inject
* @var Class2
*/
private $class2;
}
Even though the dependency will be injected by the container, the fact that Class1
depends on Class2
is fairly explicit. (dependency injection container used here is PHP-DI)

- 48,448
- 45
- 173
- 261
I asked this question 3 years ago and have since come to understand and love DI in statically typed languages.
It looks like when I asked this question I didn't understand the difference between a 'Service Locator' and a 'Dependency Injection Container' (DIC).
A DIC operates "below" the app and is responsible for constructing objects and building the object graph, typically during bootstrapping but before the app if fully bootstrapped. Classes should not be aware of a DIC and should not depend on it. The DIC should construct all of the class's dependencies and inject them as if the class was being instantiated by hand.
A Service Locator is an object that is passed around a system and used to find dependencies. Using a service locator obscures dependencies (the original problem I noticed when I was learning this stuff) and creates a system-wide dependency (i.e. the service locator itself).
Generally, I would avoid the service locator pattern (some call it an "anti-pattern"). Using a good DIC like Ninject or Symfony 2's DIC will let your classes focus on the business logic therein - not on finding dependencies.
Read Martin Fowlers article on Dependency Injection: http://www.martinfowler.com/articles/injection.html

- 6,201
- 5
- 43
- 66
It seems you can use 'depends-on' attribute in your bean definition to add an explicit dependency in your code. I have found a similar question here

- 1
- 1

- 742
- 1
- 7
- 16