Thursday, 24 September 2009

Constructor vs setter injection

Choosing between constructor or setter injection is not straight forwards and in practice can lead to difficult choices. In cases where objects have a large number of required dependencies this issue really raises its head.

Spring.Net's documentatioon states:
"The Spring team generally advocates the usage of setter injection, since a large number of constructor arguments can get unwieldy, especially when some properties are optional. The presence of setter properties also makes objects of that class amenable to reconfigured or reinjection later. Managment through WMI is a compelling use case.

Some purists favor constructor-based injection. Supplying all object dependencies means that the object is always returned to client (calling) code in a totally initialized state. The disadvantage is that the object becomes less amenable to reconfiguration and re-injection...

...Since you can mix both, Constructor- and Setter-based DI, it is a good rule of thumb to use constructor arguments for mandatory dependencies and setters for optional dependencies."
Martin Fowler also has a few words of advice on this issue:
"The choice between setter and constructor injection is interesting as it mirrors a more general issue with object-oriented programming - should you fill fields in a constructor or with setters.

My long running default with objects is as much as possible, to create valid objects at construction time.... Constructors with parameters give you a clear statement of what it means to create a valid object in an obvious place. If there's more than one way to do it, create multiple constructors that show the different combinations...

...But with any situation there are exceptions. If you have a lot of constructor parameters things can look messy, particularly in languages without keyword parameters. It's true that a long constructor is often a sign of an over-busy object that should be split, but there are cases when that's what you need...

...If you have multiple constructors and inheritance, then things can get particularly awkward. In order to initialize everything you have to provide constructors to forward to each superclass constructor, while also adding you own arguments. This can lead to an even bigger explosion of constructors.

Despite the disadvantages my preference is to start with constructor injection, but be ready to switch to setter injection as soon as the problems I've outlined above start to become a problem." -
The Spring.Net documentation goes on to point out that with constructor injection it is possible to get into a situation where you have unresolvable circular dependencies. These situations are detected by Spring.Net which throws an ObjectCurrentlyInCreationException. Spring offer some helpfull advice:
"One possible solution to this issue is to edit the source code of some of your classes to be configured via setters instead of via constructors. Alternatively, avoid constructor injection and stick to setter injection only. In other words, although it is not recommended, you can configure circular dependencies with setter injection."
In short the choice between setter and constructor is not clear and you need to make your own choice based on circumstances. This ambiguity is arguably a weakness with Dependency Injection.


Post a Comment

By all means leave a comment. I may not be able to get back to you as quickly as I'd like but I'll do my very best.