Venkat on Objects, Properties, and Constructors April 15, 2007 | 10:06 pm

I saw a great speech at No Fluff, Just Stuff by Venkat Subramaniam on Spring and Groovy. It’s an interesting technology, but what was really interesting to me was a brief exchange near the end.

One person commented that they didn’t understand the general opposition to using constructor-based dependency injection. Venkat initially gave the standard answer that constructors became unweildly with lots of properties. Sensing that was a pretty unsatisfactory answer, he went on to say that he granted that having constructor args was better from an object theory “puritanical” point of view, he found that extending his objects became more difficult.

I’m not sure this is a legitimate argument. If you really have to have mutable state, at least try to prevent your objects from being constructed in an unusable state. In addition to the theoretical nicety of not having nonsense objects, there is a deep practical (if not pragmatic) consideration: unit tests should address all significant state categories that an object can be in. If you allow an object to be in more possible states, that means you need to write more unit tests. This is time and pretty mindless effort that your compiler could spare you from if you’d let it.

But is this issue of extension critical enough to overwhelm the advantages the compiler gives? I don’t think so. If you need to extend a class, you need to pull the constructor arguments forward — this is the required state for the object which needs to be addressed. If they need to be wrapped or translated, that can be handled through static methods. If you need to generate objects piecemeal, use the factory pattern (which Spring supports quite nicely). And, in general, composition should be favored over inheritance.

One of the other people in the conference noted that Spring now has a @Required annotation. I will address that over at another blog (here).

Tags: ,

  • http://neilbartlett.name/blog Neil Bartlett

    I tend to agree – the problem with constructor args being unnamed and therefore difficult to manage is just an issue with the Java language rather than anything deeply problematic about constructors in general. If one is willing to entertain other JVM-compiling languages such as Groovy, then this problem can be fixed. (NB I don’t know Groovy so I have no idea if it has named constructor args, I’m just speaking theoretically).

    However, the main limitation of contructor injection in my opinion is that it only supports dependencies that are mandatory, unary and static. When Spring-OSGi comes along, you’re going to have more flexibility in all three of those dimensions: firstly, you’re going to get “nice to have” dependencies, i.e. bean A would like to use bean B if it’s available, but it can still do something useful even when it’s not. Secondly, you might have twenty instances of bean B and A wants to know about them all. Thirdly, you’re going to have beans that come and go, and a single instance of A might need to bind to multiple different instances of B during its lifetime. None of these use cases can be supported with constructor injection.

    So, as with most things, constructor injection is nice, but not the solution for everything.

  • http://enfranchisedmind.com/blog Robert

    To my exceedingly limited knowledge, Groovy doesn’t have constructors at all — Spring+Groovy, at least, doesn’t support constructor injection. I’ll see if I can get someone more knowledgeable to comment.

    I’m not a big fan of named arguments, particularly if I don’t have a compiler: I’ve been bitten too many times in Perl by typoing an named argument. Perl’s error swallowing (e.g. silent conversion of undef to the empty string) makes the situation all that much worse.

    Why are none of the cases you’ve described supported through constructor injection?

    Maybe I need to clarify my position a bit. I support constructor injection for properties that are mandatory: that is, for properties that are necessary to be set for the object to do its job. Once set, I have no problem with the value being changed (including collections having elements added or removed) — I just don’t ever want to be able to get an object which isn’t usable because it’s partially configured.

    Optional parameters, or parameters for which reasonable defaults can be inferred, should be left as accessor properties so that they can be cleanly ignored. I’ve just realized (by meandering blogs) that some people are advocating setting all properties at construction time. That’d be nice if Java was a functional language, but I see where that rapidly becomes a serious pain (imagine trying to programmatically work with BasicDataSource that way).

  • Pingback: Enfranchised Mind » Venkat on Functional Languages: I Knew He Was Smart