The proponents of new technologies always seem to see themselves as involved in some kind of populist rebellion. For example, judging from rhetoric, I am pretty sure that Ruby programmers see themselves something like this:

I think the underlying reason these little wars go on is that so few people are in a position to understand the trade-offs involved in a technology choice because understanding the trade-off requires understanding both alternatives. It takes a great deal of experience, and the more fundamental the change, the longer it takes. It is easy for me to like, for example, Haskell, since I have never had to build a large, reliable, non-trivial piece of software in it, I only have to see the benefits.
In any case Java had its own little rebellion not so very long ago producing a slew of “light-weight” technologies (Java’s conception of what is light-weight is very different from anyone else’s perspective so we better keep that in the quotes). The whole thing of periodically turning against the tools we use, is a bit counter-productive and kind of juvenile. But I am willing to accept a bi-yearly cycle of ecstasy and loathing to work in an industry with a little passion. Probably foremost in this mini-rebellion was the Spring Framework, which bills itself as a sort of add-on to J2EE. The core idea in Spring is “dependency injection,” which is billed as a better way of building applications out of loosely-coupled components.
It is very difficult to evaluate the effect of an idea like this which claims to improve software architecture because small programs have very little need for anything like architecture. As a consequence it is very difficult to explain the advantage of the new idea, because the advantage only because significant when you have a program of a certain size. So evaluating this kind of idea requires implementing a large system multiple times in different ways to see which is better. It should be no surprise that this takes years (the best example is the microkernel debate, where, many complete production quality OSes later, we still have both).
In any case, Spring remains quite popular and just released version 2.0. I have been using Spring for a while and I think I am ready to start reflecting on how good of an idea the whole dependency-injection-as-core-architecture choice really is. For the record I think Spring is about as good as you can do in Java-land right now. But there is a whole world of difference between better than others and good.
For those who haven’t stumbled across it already the idea of dependency injection is to make component dependencies be parameters of your objects rather than hard coding them. Thus if your program does logging (for example) using some home grown system you might do the following:
class Example{
private Logger logger = FileSystemLogger();
public void doSomething(){
logger.info("Doing something...");
...
}
The good news is that your class mostly only depends on the Logger interface (say, info, error, warn, etc.), the bad news is that you have hard-coded an implementation of Logger, FileSystemLogger when you initialize the logger. There are a lot of ways to abstract away this dependency, but the absolute simplest is is the following:
class Example{
private Logger logger;
public Example(Logger logger){
this.logger = logger;
}
public void doSomething(){
logger.info(”Doing something…”);
…
}
}
In this way whomever instantiates the Example class will have to provide the Logger implementation. And we have rid ourselves of the dependency.
This example hardly does much justice to the idea, you have to imagine you have a large collection of services bound together in this way, and then you can begin to imagine the benefits.
But in Spring the dependency injection idea is co-mingled with a few other ideas:
- XML configuration
- Aspect-oriented programming
- Fixing J2EE
- Programming to Interfaces
Fixing J2EE is where Spring is most clearly successful. If you are using straight-up JDBC you can switch to Spring’s JdbcTemplate and write 1/5th the JDBC code immediately and get free transaction handling too (which now comes with a nifty little @Transactional annotation).
The XML configuration bit is more debatable. In Spring one would implement the above example as follows [1]:
<bean id="logger" class="FileSystemLogger"/>
<bean id="myExample" class="Example">
<constructor-arg order="1"><ref local="logger"/></constructor-arg>
</bean>
Actually the XML itself is a terrible way of wiring things together when compared with Java. XML won’t enforce type-correctness, requires the programmer to learn a whole new set of Spring-specific sematics. Rather than having a applicationContext.xml file with Spring configuration XML, it is vastly simpler to have the following:
class ApplicationContext{
ApplicationConext(){
Logger logger = new FileSystemLogger();
Example myExample = new Example(logger);
...
}
}
I thought I had invented this idea when I first thought of it, but a little research shows that it turns up at the end of Martin Fowler’s essay on Inversion of Control, and a very intelligent discussion of the details of using Java-based dependency injection is given in this article. The primary advantage of using code is that the flow of control in the application remains fully documented and understandable. It is a well known problem that the Spring configuration for a large project can become a problem in and of itself. Spring has mechanisms within it help avoid configurartion file madness, but frankly they cannot compete with the mechanisms in Java itself (e.g. type-checking, inheritence, etc.).
The claimed advantage of a configuration file over source code is that one can change the configuration without having to recompile. It is true that many organizations treat configuration changes less seriously than code changes, but that is because these organizations only support primative configuration (e.g. string or number values). Spring allows you to completely rearrange the flow of control via configuration (e.g. disable all transactionality, say, or in general string together completely untested software combinations). It is true that simple properties are often maintained via dependency injection, but these are typically externalized to a properties file just as they would be without dependecy injection. I doubt most organizations that use Spring seriously allow application context xml changes without at least cursory QA verification, in which case a new build is not really much of an issue.
So I can’t say much for the XML part of Spring. I still think programs are better off as code.
The next idea in the Spring meddly is the idea of programming to interfaces. The phrase programming to interfaces is much older than Java itself, but when Java programmers use it it is not entirely clear what they mean. That is, there is programming to interfaces, and then there is programming to Java interfaces. Programming to interfaces means creating a well-defined set of publically accessible operations for your object and using only those operations. It is an excellent idea and you can practice it in virtually any programming language (for example the Linux kernel does a lot of programming to interfaces–e.g. the filesystem interface). But the Spring people seem quite convinced that you should program to Java interfaces, that is you should create a Java interface for, well, everything. The only benefits of this practice is that it will make your project look very complicated which may impress your coworkers. If you are being payed on a per-line-of-code basis you will incur a nice little 10% bonus. The downside is that, oh yes, there will be more code. And every time you add a parameter to some method in class A you will also need to add it to interface A. In other words this advice boils down to “repeat yourself unnecessarily”. This kind of thing is particularly irksome in the early stages of development when interfaces are evolving. I will go ahead an claim that there is not one single advantage in application development of programming to Java interfaces over the following:
- You need, oh I don’t know, say a logging class, and you suspect that in the future there may be many logging implementations.
- You create a class Logger.java which contains the implementation you initially plan to use. You put thought into the operations possible on a Logger, even considering the future implementations you may need. You do not create any interfaces.
- You check-in your code and release this version of your project.
- 95% of the time it ends here, but 5% of the time it becomes the case that logging becomes much more important, and you need to support more ways of logging.
- You use the refactoring functionality in your IDE to seperate Logger.java into an interface Logger.java and an implementation FileSystemLogger.java. This takes all of 3 seconds. Actually this is a nice little advantage of the Java convention of naming classes with implementation-specific details (i.e. ArrayList), and naming interfaces with a simple generic name (e.g. List).
Notice how 95% of the time creating the extra interface up front is just a waste of time, and the 5% of the time it isn’t you loose those 3 seconds required to fire up the IDE.
Now this doesn’t always hold true. It may be that you need to support two implemenations right from the get-go, in which case a Java interface is exactly what the doctor ordered. It also might be that you are writing a library, not an application–which is totally different. A library is full of code that is meant to be used without changing the code itself, and so it has to support any kind of reasonable extension. In this case up front interfaces are a requirement. But just because you are often annoyed that, say, the Java standard library didn’t do this, doesn’t mean you should go litering libraries thoughout your own application. I think one of the reasons for the complexity of many Java projects is because the programmers have taken too much advice from library developers (who are usually very good programmers and worth listening to) and they have started to act as if they did not have access to their own code. This is why your project at work has 4 trillion lines of configuration, any serious change to which will end in breakages that you will only be able to detect at runtime.
Part of this comes from the fixation many programmers have with object-oriented programming. To put this simply let me rank three things from best to worst:
- Simple requirements
- Complex requirements satisfied with two seperate polymorphic implementations (e.g. an interface and two implentations)
- Complex requirements satisfied with a morass of if statements and case-wise logic.
When you have multiple states of a system, you have a potentially combinatorial explosion of system states. That is, if you have 10 interfaces with 3 implementations each then you have 3^10 = 59,049 cominations to test. It doesn’t matter if you use the complex set of case-wise logic or the clean programming-to-interfaces style–the complexity is still potentially exponential.
Fortunately Spring only recommends that you make all these interfaces, you don’t actually have to. I think the reason must be that it was an early technical limitation in Spring before cglib. As usual when defending a technical limitation people pretend it is not a limitation at all…
Finally we come to Aspect-Oriented Programming. First of all, I think the Spring people are right that the fine-grained aspect orientation (e.g. in AspectJ) is not worth the complication, all that is really needed is the ability to wrap methods with reusable services. But how hard is it, really, to proxy a method? Before we go any further, let’s look at how easy this is too do if one has access to first order functions. Here is an implementation in pseudo-javascript:
function makeBeforeAdvisedFunction(fun, advice){
return function(){ advice(arguments); return fun(arguments);}
}
See how it works? You give a function, and you get back a function which works exactly the same, but with advice applied.
Of course this isn’t quite as powerful as Spring AOP which allows you to apply advice to many methods with a single regular expression. But is this really that necessary? I mean if applying the advice is all of 10 extra characters then is it such a big deal to add it explicitly? Furthermore, isn’t it beneficial to have everything right there, explicitly spelled out, rather than having code invisibily inserted at runtime?
I don’t really know the answer to this. I suspect that the phrase Aspect-Oriented Programming is a complete misnomer, since your project is unlikely to become Aspect-Oriented. It may feature Aspects for say four or five essential services, but the idea that it would become completely oriented towards aspects is a complete oversell[2]. The whole point is that there are a few key things repeated all over. The ones that most all programs share are transaction management, caching, and audit trails (recording all the changes to an object), and security checks, plus a few that are probably domain specific.
A truely aspect-oriented program sounds like a disaster. How would one debug such a beast if it were composed of bits and pieces of code glued together from all over without any clear control-flow? But for the specific examples above it is a compellingly non-invasive way to add a reusable services on top of an object.
[1] Actually Spring advocates using setter methods instead of contructor arguments for setting properties. They argue that this is more flexible. I agree that it is more flexible, but I think it is more dangerous. First it forces you to implement setter methods for properties, even though it may be either meaningless or disasterous if anyone calls those setter methods after initialization (for example what happens if someone calls setDataSource on your data-access object in the middle of a transaction…I don’t know but i can’t think of what a correct behavior is in this case). Secondly it makes it very troublesome to ensure the validity of your object because one cannot enforce any requirement on the complete set of parameters. This deficiency is partially overcome by the @Required annotation available in Spring 2.0. But of course this means every property must be either required or not, it can’t be the case that one either provides A or provides B.
[2] In addition to a tendency to oversell itself the whole Aspect-Oriented thing is completely terminology heavy, and the terminology is particularly wretched (point-cuts, join-points, etc.). It’s a pretty off-putting combination of commercial salesmanship and the pseudo-academic phraseology they developed. But you know, we shouldn’t let that kind of thing sink good ideas if they are there.
360731 Blog Verification | 17-Oct-06 at 1:14 am | Permalink
360731 Blog Verification…
360731…
Patrick Bourke | 17-Oct-06 at 4:11 am | Permalink
“Spring advocates using setter methods instead of contructor arguments for setting properties”
While setter injection tends to appear more often in the Spring documentation, constructor injection is equally valid and fully supported. I find that constructor injection tends to minimise errors in object configuration. It allows you to validate required collaborators in a normal Java constructor, rather than creating some artificial “init” method or introducing a dependency on the framework. It also helps to limit the number of states that an object can occupy.
I agree with your points on AOP. Like many tools, it’s useful only insofar as it helps us to manage complexity.
Wes Maldonado: Data Junkie » Blog Archive » The Number One NIH Syndrome Sympton (or, How I learned to not invent wheels and learned to love 3rd party components.) | 26-Oct-06 at 1:52 pm | Permalink
[…] I was happily reading The Ideas in the Spring Framework for Java that covered the basics of Dependency Injection using Spring and linked to another article, Dependency Injection without Frameworks… which screamed of NIH and slightly ruined my day. […]
Sijin | 27-Oct-06 at 9:28 am | Permalink
Right on regarding the “Program to an interface part”, see my post on a similar topic http://www.indiangeek.net/?p=41