Page 45
The author suggests that there is an ongoing debate on the issue of constructor injection vs. setter injection, and provides arguments for each one of them. Unfortunately, in the arguments that he provides for constructor injection he paints a straw-man, while his arguments for setter injection are all non-issues. It is no wonder then, that at the end of the discussion his personal preference turns out to be setter injection.
Arguments for constructor injection:
Of course, this assumes that the bean’s constructor has all of the bean’s dependencies in its parameter list.No, constructor injection does not assume that; instead, it requires it, because that's precisely the point of constructor injection. It is quite unfair to take the central premise of constructor injection and reword it as a drawback. Perhaps the author meant to say instead that constructor injection assumes that all of the dependencies are available at the time of the construction of the bean. Well, the only case in which a dependency might be unavailable at construction time is if the design of our system has a circular dependency built into it. In which case the flaw is with our design, not with the concept of constructor injection! Correspondingly, I favor the use of constructor injection everywhere, and in the rare and unfortunate case when a circular dependency exists and is not easy to factor out, the exceptional use of setter injection as a self-documenting means of temporarily circumventing the problem.
By only allowing properties to be set through the constructor, you are, effectively, making those properties immutable, preventing accidental change in the course of application flow.This is taking a very important benefit of constructor injection and wording it as if it was a minor advantage. The issue is not just the possibility of accidental change; the issue is the fundamental object-oriented concept of encapsulation, which mandates that a class should not expose its internal members to the outside world. The dependencies of a class are, by definition, its own private business. By making every single dependency of a class available for anyone out there to modify via a setter method, encapsulation goes out the window. The dependencies might as well be declared as public non-final members, it would make no difference.
Also, the issue of immutability goes beyond just the members of the bean; if all members of the bean are immutable, then the bean itself becomes immutable. The benefits of immutability are widely known, and I should not need to list them here, but let me briefly just mention thread-safety-for-free, reduction of overall program complexity as a direct result of statelessness, and the ability to use an immutable class as a key in a map.
Arguments for setter injection:
If a bean has several dependencies, the constructor’s parameter list can be quite lengthy.So what? By the same token, if setter injection is used, then the list of setters will be quite lengthy. This is not an argument.
If there are several ways to construct a valid object, it can be hard to come up with unique constructors, since constructor signatures vary only by the number and type of parameters.Oh, puh-leez! if there are several ways to construct the bean, (a small possibility,) and if it is hard to come up with unique constructors, (a minutely small possibility,) then someone, somewhere, will have to squeeze their brain a little bit more to come up with unique constructors. If one does not want to have to think at work every once in a while, maybe they should not have become a programmer. Also: with constructors, there are only so many ways to construct a bean as there are constructors for it. With setters, there exist something of the order of number-of-setters-factorial number of ways to construct it. What do you prefer?
If a constructor takes two or more parameters of the same type, it may be difficult to determine what each parameter’s purpose is.Yeah, sure. Let me help: the 1st parameter will have purpose A, and the 2nd parameter will have purpose B. And if you ever find yourself in doubt, hover your mouse over the invocation, and your IDE will be very happy to clarify it for you. (Or use a better language, like C#, which allows you to supply parameter names in invocations.)
Constructor injection does not lend itself readily to inheritance. A bean’s constructor will have to pass parameters to super() in order to set private properties in the parent object.Wha-what? Constructor injection does not lend itself readily to inheritance? Is the author ignorant about the concept of constructors or the concept of inheritance? Of course a bean's constructor will have to pass parameters to super, and it will have to pass exactly those parameters that the super requires, and that's precisely what guarantees proper instantiation of the super, and that's the whole point with using constructors, and a very important premise of inheritance. Again, a feature presented as a drawback. It is not a sign of a wise man to make the same mistake twice.
In short, I do not believe that there really is a debate; it is just that eternal difference in world views between the real engineers, who are compelled to build compiler-enforced robustness into their software, and those who are programmers by accident, and prefer a certain cozy amount of sloppiness sprinkled everywhere for the sake of some ill-perceived ease in coding, testing, or refactoring. It really is the same short-sighted mentality that says "I make all members public because this way I can access them easier." Part of the problem might also be some ignorance-induced superstition, on behalf of the second group of people, against the use of constructors. I have seen it again and again: many people simply do not get constructors. And people tend to fear the unknown.
Page 62
"Furthermore, if a constructor has multiple constructors, [...]" should read "Furthermore, if a bean has multiple constructors, [...]".
Page 80
"It just so happens that the Harry, [...]" should read "It just so happens that Harry, [...]".
Page 85
"Even though it’s prototype scoped, the guitar method would only be injected [...]" should read "Even though it’s prototype scoped, the guitar bean would only be injected [...]"
Page 141
"Spring’s basic autoproxy facility is fine for working with simple advice or when in a pre–Java 5 environment. But if you’re targeting Java 5, you may want to consider Spring’s support for AspectJ’s annotation-based aspects. Let’s see how to create aspects in Spring that are annotation based."
Well, I am kind of disappointed by the fact that I had to read 24 pages of "Spring's basic autoproxy facility", which is another way of saying "advising the hard way", in order to finally reach section 4.3.2 "Autoproxying @AspectJ aspects" where advising begins to make sense. Couldn't we have just skipped most of that stuff?
Page 173
It’s like the Pareto principle2 flipped on its head; 20 percent of the code is needed to actually query a row while 80 percent is just boilerplate code.--excellent observation!
"This is all the more reason to let a framework deal with the boilerplate code so that we know that it written once and written right." should read "This is all the more reason to let a framework deal with the boilerplate code so that we know that it is written once and written right."
Page 211
"it’s better to keep thing separate" should read "it’s better to keep things separate"
Page 239
The word "suspect" should be "suspend".
No comments:
Post a Comment