Spring Revisited

Recently I retrofitted some code I was working on to utilize Spring. It's been some time since I'd used it and I'd forgotten how much I enjoy coding in this framework. It really helps me write better, cleaner code.

As developers, we always strive to create plug-and-play architectures - you know, code to an interface, achieve easily swappable implementations, etc. That in itself really isn't that hard to do, but Spring really shines in enforcing this idea. My original code (for Jena) needed to grab some Resource references from the model and looked something like this...

{method declaration}
OntologyModel model = {get model reference}
URI resourceUri = new URI("http://www.myCompany.com/MC#myResource1");
Reoruce myResource = model.getResource(resourceUri);
{additional business logic}


The equivalent Spring configuration replacement for this code looks like this...

<bean id="myResource" class="com.myCompany.Resource" factory-bean="model" factory-method="getResource">
<constructor-arg>
<bean class="java.net.URI">
<constructor-arg value="http://www.myCompany.com/MC#myResource1"/>
</bean>
</constructor-arg>
</bean>

The major difference is in the in the {get model reference} statement. In the Java version, I'd normally gain access to the model using a Service Locator or a Singleton. Whatever design choice was made, would find its way into the implementation as "Model.something" or "(OntologyModel)Locator.get("model")".

With Spring, the framework wants you to inject the model dependency into the class. This forces you to pull up the method local OntologyModel reference to a higher level (either as a method parameter or a member variable).

This refactoring has a few pleasant side effects. First of all, it makes the business logic in the method itself a little cleaner - gone is the code clutter to figure out how to get the reference or where it's coming from. The method is reduced to it's essential business logic.

Secondly, the fact that this method or class depends on and utilizes OntologyModel is made explicit through it's interface. This is a good thing (really). In the past, I've argued that one job of the class is to abstract away (or encapsulate) this dependency or complexity, but I've sort of changed my thinking a little on this. Sure, you might not want to expose whether your code is using a JDBC or a JMS connection or gets its value over HTTP, but what you want to change in this case is your level of abstraction. Wrap the HTTP/JMS/JDBC connection in another class interface and expose that instead. It's exactly this functionality which make Spring so appealing to me because now it's trivial to change the Spring configuration between alternative HTTP/JMS/JDBC implementations or stub these out completely for unit testing. With Spring, not only is this functionality "baked in", but the framework encourages this behavior.

Finally, because the behavior of the code can be changed outside the compiler via classpath configuration files, the same jar can used for unit test, QA, and production. Not having to rebuild your code for various environments ensures that your build configuration doesn't introduce any unintentional side effects into your code. I was on a project once where different files were included into a war depending on which region it was destined to run. When incompatibilities were uncovered between the code running in each region, you needed to check the environment of the physical system, any external configuration file overrides, and the code itself. If the same code is deployed to each region, you eliminate one of these things you need to check.

I'm happy to be back using Spring because it helps achieve and enforce the goals I set for myself and my team in developing quality software. My code is cleaner, more modularized, and easier to extend.

Comments

Popular posts from this blog

FRail :include

Performance Tuning JCAPS - Part 2

I Believe...