The case against dependency injection (in its common form)
Dependency injection as it seems to be commonly used in Javaverse, is at the center of what I consider problematic (read sucks) with the philosophy behind JEE.
To be clear: annotation-driven dependency injection is a reasonable software pattern. For example, it allows defining partial standards such as JAX-RS. However, dependency injection as the default mechanism (i.e. with one global namespace) for interconnecting beans makes sense only for small projects.
Dependency injection is often sold with the argument that it solves the problem of constructors with long argument lists. The problem with this sales pitch is that having ten arguments to your constructor or having ten injections on your class both amount to an unsurveillable mess. Put differently, ten constructor arguments or ten injections make no difference to a unit test.
Both JAX-RS and stateless beans are (more or less) instantiated per request. Given the low cost of instantiation this makes sense as an isolation mechanism, but since classes are just used to group responders that are related (operate on similar data, use shared helpers, et cetera) each responder method is likely to require a slightly different set of injections. The grouping class ends up with the union of all injections. The result is a chaotic network that is hard to create a mental map of. Where dependency injection has created such networks, isolating functional units for testing becomes much harder. Massive mocking ensues.My position is that in order to be comprehensible and unit testable, any large software project needs to be divided into subsystems. Each subsystem should be a namespace unto itself. Its interaction should be isolated properly, e.g. using a message passing pattern (a message queue in JMS terminology). A system thus subdivided will not suffer from unwieldy constructors. It could still use dependency injection internally for e.g. plugins.
- Log in to post comments