Java has lately been seriously annoying me in this regard. Why do I have to write getters/setters for beans? Why can’t we just have a property keyword instead that does it automatically? Why does everyone insist on using getters/setters in the first place rather than public fields anyway? What’s the point? Ah, yes, we need to be able to proxy the methods through cglib for Hibernate, or via Spring’s IoC/AOP stuff, so we can write “better” code with fewer dependencies.
For all Spring’s AOP wonder, for all its magic wiring of interfaces that make things harder to debug, for all that, what have we really gained?
Myth #1: “Your code is less coupled, which can only be good.”
Err, no it isn’t – it depends on Spring. If I wired it together using plain Java I’ve have fewer dependencies and no awkward XML that my IDE doesn’t understand semantically and can’t type-check. It’s true that Spring encourages you to introduce fewer couplings, but a good Java coder or architect will do that anyway. I hope you don’t entrust the design of your app’s top-level components and how they should talk to each other to someone who’s a bad coder.
Myth #2: “It makes the dependency injection easier!”
Well, yes and no. You can use the clever autowiring. But then you run the risk of maintainers not understanding which things are wired together and how it all works. The Spring manual itself admits:
Autowiring is more magical than explicit wiring. Although, as noted in the above table, Spring is careful to avoid guessing in case of ambiguity which might have unexpected results, the relationships between your Spring-managed objects is no longer explicitly documented.
Well, great: If I’m maintaining someone else’s project and need to bump the Spring version number, is that magic good? What if the behaviour changes due to a bug/fix, and it breaks? How do I even know what the relationship should have been?
To quote the Spring manual again:
In most cases, the answer to the question of whether you should use auto-wiring is definitely “No!” Auto-wiring can save you time in small applications, but in many cases, it leads to bad practices and is inflexible in large applications.
So if we ditch that, what does Spring IoC buy us? It works out the ordering for dependency creation and injection. My IDE does that trivially – shuffle things about ’til the squiggly red lines go away. This isn’t really a hard problem that needs solving with special tools, IMHO. If you do it in Java you then have the advantage that you’ll know what the order will be just by reading the easy-to-understand code. Look, you can even set breakpoints during your context initialisation and everything!
Myth #3: “Only IoC enables you to update the configuration without recompiling.”
So does Java. If you need to do that, put the configuration in a properties file. Which is probably what you’d be doing anyway, with Spring’s PropertyPlaceholderConfigurer. Even ignoring that, who actually does this on live systems? Particularly for webapps, you’ll want to build a WAR. You’ll have some kind of build system for that, right? Are you really going to unpack the existing WAR and edit the XML? Or are you going to edit the XML and run the build script? If you do the former, how do you know your newly edited context will work? You have unit tests for that, right? Which get executed when you run the build scripts, yes? So, why is updating a Java file considered to be such a big deal?
The worst aspect of all this, alluded to in the rest of this post, is that we write mountains of IoC configuration in XML, of all things. To be able to maintain such a project, you need to be able to grok the XML. And Point #3 on w3c.org’s XML synopsis is “XML is text, but isn’t meant to be read”. XML should be parsed by machines. Java should be parsed by humans first, and machines second (at least if you want your code to be maintainable). Spring configuration appears to be sufficiently hard to read that people are now pushing Spring config using domain-specific XML. Great – I now need to learn an entire new grammar to be able to configure each niche library/technology/product! Someone tell me again why everyone is replacing trivial Java with nasty XML full of magic?
Myth #4: “You can replace Hibernate with something else, and your API consumer doesn’t have to change anything, because it’s all just interfaces!”
Err, yes. What’s to stop you writing against your interfaces and making a factory class for your DAOs which hides the Hibernate bits as much as possible? Why would you need IoC for that? Besides, has anyone ever actually done this? If you can find a complex app where replacing the Hibernate layer with some other technology would involve no DAO interface changes, I’ll eat my hat. Hibernate and your DAO interfaces are an abstraction. Abstractions leak. Lazy-loading, in particular, leaks like a sieve, all the way across your nice tiered app. Ah, implement an OpenSessionInView filter, I hear you say. Which promptly leaks in three-tier designs where your domain objects are pulled across RMI or whatever.
Oh, why do we torture ourselves so?