Archive for the ‘ Java ’ Category

Why I wish Spring IoC was not marketed as a DI framework


I recently came across Guice, a framework that is widely considered an alternative / competing Dependancy Injection (DI) framework to Spring’s IoC container. After reading the documentation (which was very good), and playing around a little, I started to read the numerous articles blog posts comparing the two, as I was personally very surprised that there was even to be a comparison to be made.

Most comparisons I read centered around the use XML vs. annotations (although Spring does allow for the latter as well), and other distinctions that entirely miss the real observation that should be made. While Spring’s IoC container certainly does do dependency injection, it does so as a side-effect of doing something much more general, that no other DI framework I have seen does well: creating and configuring instances of Java objects. Sound like a boring and uninteresting statement? Well, this is a very subtle and powerful point whose ramifications are not obvious, but really should be understood in order to get the most out of Spring’s IoC container and change the way you program (for the better). Let me elaborate.

Most DI frameworks focus on saving you from having to write a lot of object factories to bind the concrete implementation classes to the interfaces exposed to and used by the rest of your codebase (i.e. bind the <code>PaypalBillingService</code> class to all places in the codebase where the <code>BillingService</code> interface is used). Spring’s IoC container does this too, and for many, this is all they use it for. But the real power of Spring’s IoC container is in its ability weave together complex graphs of Java objects and configure them with values.

Consider a simple example of a class meant to represent a JDBC configuration, and a goal of creating JDBC configurations for your development, qa, and production databases.

// I will use the non-compilable shorthand 'property TYPE NAME' to represent Java Bean properties and save me from
// writing getters and setters in this example

public class JdbcConfiguration {
    property String driverClassName;
    property String jdbcUrl;
    property String username;
    property String password;
}

I can then define beans for each configuration:

<bean id="myDevJdbcConfig" class="com.acme.JdbcConfiguration">
   <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
   <property name="jdbcUrl" value="jdbc:mysql://devserver:3306/mydb"/>
   <property name="username" value="admin"/>
   <property name="password" value="admin"/>
</bean>

<bean id="myQAJdbcConfig" class="com.acme.JdbcConfiguration">
   <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
   <property name="jdbcUrl" value="jdbc:mysql://qaserver:3306/mydb"/>
   <property name="username" value="admin"/>
   <property name="password" value="admin"/>
</bean>

<bean id="myProdJdbcConfig" class="com.acme.JdbcConfiguration">
   <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
   <property name="jdbcUrl" value="jdbc:mysql://prodserver:3306/mydb"/>
   <property name="username" value="admin"/>
   <property name="password" value="admin"/>
</bean>

What’s interesting in this simple example is that I used Spring more to configure instances of a single Java class than to provide Dependency Injection in the way that other frameworks like Guice are primarily used.

But this example was somewhat trivial, so let’s kick it up a notch. At my last company, Merced Systems, our professional services team was able to implement incredibly complex customizations of our core platform for our customers using only configuration (no code) using an IoC container I wrote in 2001 very similar to Spring’s (enough like Spring’s that I will use Spring to illustrate).

Let’s say we have a simple ETL (Extraction, Translation, and Loading) framework for moving data from a source database to a target. You could use Spring to completely define an entire ETL process by linking together a set of Java Bean instances:

(I will omit class definitions as they will be obvious from the structure of the bean definitions)

<bean id="myETLConversion" class="com.acme.ETLConversion">
   <property name="source" ref="source">
   <property name="target" ref="target">
   <property name="mapping" ref="mapping">
   <property name="startTime" value="12:00am EST">
   <property name="frequency" value="DAILY">
   <property name="adminEmailForErrorAlerts" value="admin@fooco.com">
</bean>

<bean id="source" class="com.acme.ETLTableEndpoint">
   <property name="tableName" value="PERSON">
   <property name="jdbcConfig" ref="mySourceJdbcConfig">
</bean>

<bean id="target" class="com.acme.ETLTableEndpoint">
   <property name="tableName" value="PERSON">
   <property name="jdbcConfig" ref="myTargetJdbcConfig">
</bean>

<bean id="mapping" class="com.acme.ETLMaping">
   <property name="columnMappings">
      <list>
         <bean class="com.acme.ColumnMapping">
            <property name="sourceColumn" value="PERSON_ID"/>
            <property name="targetColumn" value="ID"/>
         </bean>
         <bean class="com.acme.ColumnMapping">
            <property name="sourceColumn" value="FIRST_NAME"/>
            <property name="targetColumn" value="FN"/>
         </bean>
         <bean class="com.acme.ColumnMapping">
            <property name="sourceColumn" value="LAST_NAME"/>
            <property name="targetColumn" value="LN"/>
         </bean>
      </list>
   </property>
</bean>

At Merced we used this technique to allow our customer services team to customize almost every single aspect of our product. In addiction to the (simplified) ETL example above, we used it for:

  • Defining Report table layouts and Chart configurations (like Bar Charts vs. Line Charts, font colors and sizes, etc…)
  • Defining the content and layout of Dashboards
  • Defining customizations of our DB schema (which we would then plugin to our ORM framework)
  • Customizations of our URL structure
  • Customizations of left-nav elements for different User roles
  • Access control rules
  • Internationalization and localization
  • More, I just cant even remember…

And… very importantly, for customizing aspects of the product the engineering team had never even anticipated. Because we had a development discipline of exposing almost every object in our codebase as a configurable Java Bean, our professional services group and customers were able to a accommodate numerous unanticipated customization requests without the need to change our codebase.  Did this mean a typical deployment of our system had hundreds of XML bean definitions? Yes. Could the configurations get very complex? Yes. Was it scary? No. It allowed us to deliver a highly customizable enterprise software product with ONE codebase, and we never had to support and rationalize Java code written by professional services, customers or outside integration shops. All customization was done via configuration and it was beautiful.

The point is, using Spring’s IoC framework to inject class dependencies as a substitution for class factories is just the beginning. It’s real power is in creating object graphs of components to drive the functionality and behavior of your system in ways that most think require code. Sure, it can result in a enormous amount of XML, and yes, the Java compiler can catch a lot more typos than Spring’s bean XML parser, but the less Java code you have, the better, because writing code causes bugs (even when you have a compiler keeping you type-safe).

I have come to realize that Spring’s IoC framework is often compared to DI frameworks like Guice and other’s because of it’s name. The term “Inversion of Control” is pretty much used interchangeably with “Dependency Injection”, and hence the comparisons. And so, I think Spring’s IoC framework suffers because of it’s name. It’s name does not do its power justice and results in naive comparisons to other frameworks. Maybe it should be called a Bean Configuration Framework, or Component Configuration Framework… not sure… but I wish it was not simply marketed, and therefore perceived, as a means for doing Dependency Injection just so that I might use a <code>PaypalBillingService</code> as my programs’s implementation of my <code>BillingService</code> interface. Its much more than that.

Java Generics – were they a good idea?


No. I think that all told, while implemented with the best of intentions, Java Generics were a bad idea. While they do provide welcome and useful functionality in some cases, overall the costs outweigh the benefits.

Cost

This new language feature and its use throughout the new Java 1.5 libraries have added a significant amount of complexity to the world of the Java developer. From the slightly counter intuitive (e.g. List<String> is not a subtype of List<Object>) to the profoundly metalicious (e.g. Enum<E extends Enum <E>>), generics can be subtle and difficult to fully understand for the average Java developer. Ask the average Java 1.4 programmer to read and explain this to you:

TypeVariable is the common superinterface for type variables of kinds. A type variable is created the first time it is needed by a reflective method, as specified in this package. If a type variable t is referenced by a type (i.e, class, interface or annotation type) T, and T is declared by the nth enclosing class of T (see JLS 8.1.2), then the creation of t requires the resolution (see JVMS 5) of the ith enclosing class of T, for i = 0 to n, inclusive. Creating a type variable must not cause the creation of its bounds. Repeated creation of a type variable has no effect. (http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/TypeVariable.html)

Yea.

Benefits

So what do we get for all this? The way I see it, there are really only two benefits to Java generics:

(1) They allow the compiler to catch some programming errors that would otherwise be detected at runtime as ClassCastExceptions (i.e. generics can prevent you from placing an Integer into a List of Strings).

(2) They make *certain* declarations more “self-documenting”. If I see a method signature that declares a parameter as a List of Strings (List<String>) it is much clearer to me how to use the method correctly and is more reliable than the documentation, if it even exists.

Net net

For me, it’s not worth it. So I have to cast more and perhaps catch some programming errors at runtime. In my experience the vast majority of ClassCastExceptions are the result of programming errors that you will catch very early while running and testing your code anyway. You fix the code and move on. Also, if you structure your error handling correctly, you should not need to wrap each cast in a try/catch block. Bottom line: the core problem generics aim to solve is not that bad of a problem.

As for (2) I would have to say that for every example of code that generics have made easier to understand there is at least one example where it has done just the opposite. Furthermore, in real-world programming with real-world class names method signatures become multi-line monsters that are quite ugly, hard to read, and a real burden to type (so much for the keystroke savings of not needing casts).

Adding language features are a big deal. You can’t undo them and they can have far reaching consequences. Java as a language, its documentation, the number of concepts its user has to manage, and the user’s learning curve have become much more complex for marginal benefit. Any addition to the language should have the effects of making programs easier to both read and write, making concepts simpler to express, and enabling the programmer to be more productive. If anything I would have liked to have seen the addition of multiple dispatch to Java (sometimes called generic methods (yes confusing) – perhaps more on this in another post).

Do I use it?

For the cases where I have no choice (grrr) and for the cases where it truly is a harmless perk (like Map<String, List>), yes, sometimes. Otherwise I avoid it.