Feeds:
Posts
Comments

Posts Tagged ‘Architecture’

Tools are cool. Ironically, you can trace this back to when humans first banged two rocks together to make fire. This historic moment moved mankind into a new era. Then they used those same rocks to beat each other to death. And therein lies the problem: if you want to kill someone, there are better tools available than a couple banged-up, rounded stones. However, it can work if you apply the operation enough times, and that’s why it took so long to come up with more useful weapons.

While that specific problem has been solved over and over and (…) again throughout the millennia, the mindset still exists in everyday life: we have a tool, it mostly works, why bother and/or risk looking for something better?

Back to the theme of this blog: software engineering. The old adage, “If the only tool you have is a hammer, everything looks like a nail,” has found its home in our profession. There are many facets to this issue in software engineering, so I’m going to do what a good software engineer should do: divide and conquer. So, first up: using XML for dependency injection.

One of the key issues with DI early on was who does the injection, and with what? The answer initially was plain old factories, preferably near the “top” layer of code. This introduced some new problems: factories were tedious to write and maintain, and implementations were tightly-coupled to the factory code.

Spring to the rescue! The Spring Framework allows us to avoid having to create these factory classes by moving the wiring logic into a separate XML configuration file. Unfortunately, this approach has its own set of issues:

  • The class names are hard-coded in the XML file. What if we misspelled the name of the package or the class? What if it’s not the right class? Well, we won’t find out until run-time. We lose the compile-time checking that a simple factory class provides.
  • Casting is required to get beans from a Spring BeanFactory (configured via the XML file). Sometimes casting is necessary in general, but it should serve as a warning flag that there may be better ways to solve the problem. In this case, it’s a subtle reminder what’s happening under the hood: reflection is being used to instantiate everything, so types are checked at run-time. You lose Java’s handy compile-time type checking that you get by using a simple factory.
  • It’s fugly. Seriously, take a look at a simple beans.xml file used to inject a Service implementation a client needs:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
    
    	<bean id="myClient" class="com.acme.Client">
    		<constructor-arg>
    			<bean class="com.acme.service.MyService">
    		</constructor-arg>
    	</bean>
    </beans>
    

    You always need to specify the full package and name of the classes (which, by the way, makes refactoring and renaming very difficult), the XML namespace stuff is a mess, and expressing “Client myClient = new Client(new MyService());” takes 5 lines of verbose XML. The tediousness of creating simple factory classes hasn’t been resolved by resorting to XML.

  • Let’s say we had a service that had two different implementations: one that saved data to a database, and another that used a file. Which one to use would be the decision of whoever is operating the application. How could they do that with a Spring XML configuration file? We could give the Ops dude the whole XML file and explain to them all of their available options. This exposes a lot more to them than they need or want, making it very difficult to make simple changes, not even taking into account future changes to the application. Ideally, a simple configuration file would be exposed to Ops, where they can choose “storageType=database” or “storageType=file”. The code would then select the appropriate service to use. Thus, you’re back to using a factory class. Spring has ways of wiring this into the configuration, but have you really gained anything by using it?

So, by decoupling it from the Java code, you’ve coupled it with non-Java code (the XML configuration file) instead, you lose static type-checking and other compile-time checks you would have normally had, and you’ve made it harder for the user to configure the right way. Wiring together program components is a programming concern, and thus should be part of the code. Throwing XML at the problem will not help.

What appproach should we take to perform dependency injection then?

Spring has a way to support injection using Java 5 annotations. This is a step in the right direction, but you’re still tied to the Spring configuration file to specify the actual beans to inject. Guice has much better support in this regard — there is no external configuration file. Instead, the user creates a “binder”, which is a type-safe way to bind a class with a particular implementation to use. This is effectively a simple factory, but it requires fewer explicit bindings. It also has what’s effectively a domain-specific language for specifying bindings, making it even more concise. Everything is made completely type-safe, thanks to Java 5 generics.

Some others have made similar observations regarding Guice:

  • Bob Lee talks about how Guice keeps everything type-safe and avoids having to keep XML in sync.
  • Debasish Ghosh uses Guice as an example about how modern Java frameworks can completely avoid arcane implementations of a dynamically-typed language in a traditionally statically-typed language.
Advertisements

Read Full Post »