While looking at Guice, I started to think about the decisions I make when I code. One of these decisions is how tightly I couple my code with third party code.
We had a problem today at work with BDB. It wasn't BDBs fault; I changed something and introduced a rather nasty bug that QA didn't catch, so data wasn't persisting correctly (BTW, no SQL in the runtime FTW). But this raised the point that, if we had written the code, we could have made it safer. This gets into the classical "Buy versus Build" problem, but I'll sidestep that and focus more on how tightly bound our code is to BDB in this case.
Our primary service has a service interface and a BDB specific provider. If we needed to swap something out it would be both contained and easy; we'd simply implement a new class based upon the previous interface, since the logic for the application is strictly contained within the storage mechanism (it's a simple service, stores data, retrieves data).
This is a pretty standard model in the Java world. I've called it the SPI model for a long time, but I think it has a different name, but anyway, the gist of the matter is you have a core set of APIs that consumers use, and a set of "internal APIs" (called SPIs, the S is for suck, er, Service) that people providing that APIs implement. There's some glue code in-between for consistency, management, or whatever else the "framework provider" is offering.
I thought of another case where I've abandoned this idea completely, and yet have managed to both survive and even excel, namely the dreaded Logging. Why is logging so painful? Because, like UI design, everyone has an opinion and a set of requirements that are greatly divergent. Anyway, there's JUL (java.util.logging), Log4j (from Apache), Commons Logging (also from Apache, woot), homemade loggers created by people unfamiliar with code reuse (or Google), and then whackjobs who created frameworks years after these have been around (I'm looking at you Sun, with JUL).
Now, the "standard" SPI would be JUL, because the JDK provides it for you, it does... most of what you need, and worst case, Log4j/Commons Logging/etc have bridge code to take your log messages from JUL to their logging subsystem.
So why do I doggedly use Log4j? Well, after thinking back, I realize I use it because I know how it works and it was (is?) far less complicated than the other options. Or at least, it's the evil I know. I probably should switch to using JUL and inject Log4j after the fact (as my preferred logging API). I probably should also inject the logging object itself, although that seems like a cross cutting concern of sorts... anyway.
I started bitching about Guice months ago, by saying "Jeez, it makes you tightly bind to their libraries!". Not really realizing I already make this choice in several ways, I didn't think much more of it, but now realize that... well, I do this with Spring too. We (at work), myself, and I have enough Spring configuration lying around to choke a cat, and it is, effectively, code.
Configuration as code! Exactly what I was hoping to avoid. I mean, that's the point of configuration, right?!?!? It's only the bits you need to tell the app what to do. However... sans some sort of Workflow Configuration Management Engine (wha?), we end up "telling the app what to do" by wiring together disparate components, feeding each one configuration (as XML, with Spring).
So, I tightly couple my configuration, er, code-as-configuration to Spring at this point. I can't "Just Startup My Application" because I need Spring to put the pieces together for me. The pieces can be reused without Spring, which is a bonus, but... not really. They still have to be wired together. And you still have to have the libraries I've used (log4j, etc), and you'll probably have to use Ivy to get them, since I patently refuse to check Jars into my SCM.
Where's my flexibility of not having tightly coupled code? I don't think I have it, actually. It'll be just as much work to run away from Guice if I wire it into code as to replace the Spring configuration going to Guice. I think. I plan to find out, at least.
Anyway, the gist of this screed is "The choices I've made in the name of flexibility haven't really given me more flexibility". I've simply traded one set of configuration for code, and vice-versa. I still have to test the application with the configuration (which is hard-ish with Spring, actually, since I don't like inheriting from their objects).
I've come to the opinion that Annotations probably don't suck as much as I previously thought (despite the fact that after using 1.5 for ... years (I think)), I haven't used them, Guice provides a compelling usage. And annotations are probably easier to remove from code than actual object usage (like log4j).
So, I'm going to :
- Try Guice
- Take another look at Annotations
- Not worry so much about my choice of libraries and tight binding... for now