Does “Inversion of Control” promote “Anemic Domain Model”?
My impression is that projects using a DI framework like Spring or Guice tend to lose their object orientation and degenerate to a purely procedural design:
DI not only centralizes the question of which implementation of an object to use but also manages the life-cycle of these objects. Many OO design patterns, however, rely on the ability of business logic to wire objects. I wouldn't know, for example, how to implement a Strategy Pattern in Spring because the decision which of the concrete strategies to use, is statically determined by the configuration of the application instead of a piece of code. Same goes for decorator, composite, observer, ...
The reason above leads to a design where functionality and data are separated. Because you don't want to let the DI container decide when data is created, you split any code off the data in order to have only this part managed by the DI container. This is contrary to the idea of OO where code and data should reside together in one unit. This breaks the encapsulation of data because all fields of the data "beans" are exposed by public getters and setters.
You can't use polymorphism anymore because code is not linked to its data anymore and the "virtual functions" can't work. This leads to those instanceof cascades that we all know we shouldn't use. Also, we lose all those designs that rely on polymorphism.
The DI container will inject managed beans only in objects which are also managed by it. So you can't mix managed beans and normal objects because there can't be any "non-managed gaps" in the reference chain of managed beans. So once you started with DI, you need to put all other code under the control of the DI container and you can't use normal objects anymore. I suppose that this is the reason why the separation of code and data is done so rigorously in DI projects.
I see that there are reasons why to use DI but is it really worth giving up so much? Don't people care about OO? Apart from this article, I can't find any discussions on this topic.
Or is it just me who doesn't understand how to do this properly? Any ideas how the four points above can be tackled with?
Appendix 1: Explanation of strategy pattern
I refer to the example here. Let's assume there's a DI version of it where all implementations of
Strategy and the
Context are injected to
StrategyExample doesn't decide anymore which
Strategy to inject into
Context but the configuration would have already decided which implementation to inject into
Context. So yes, DI heavily applies the Strategy Pattern. But it always does so statically.