Random musings from my awakening dementia...
05.18.2004  
Loosely Coupled Components, Part 1
 

I'm quite interested in the concept of software components and how those ideas can be applied to Java code. Thoughts or ideas I have on this subject get dropped here for the benefit of humanity and my own hubris.

© 2004-2005, Howard Abrams



Except where otherwise noted, all original content is licensed under a Creative Commons License.
See details.

I have mentioned often that one of the major keys to building good software components is independence… that is, having code that doesn’t have dependencies on other code. This is all great in theory, but as soon as you have a component make a function call to another component, you have just created a dependency.

Of course you are now saying, how would you build an application if you can’t hook components together… Function calls are only one way of integrating components together, we call this approach tight coupling.

There are places where tight coupling is fine. For instance, if you create a servlet that makes function calls and object instantiations from one or more components, you are creating a dependency where the servlet depends on these components. But servlets are generally application specific, and therefore not reusable, so such a dependency is usually acceptable.

However, if you have to get data from one component to another, then your servlet should get the data from the first component and pass it to the other component… don’t get tempted to have the component pass the data directly, otherwise, you create an unnecessary dependency (see the following illustration).

Component Dependency Illustration

But what if you wanted to make your servlet (or other caller) independent? This is where we get into the realm we call loose coupling. The idea here is to instantiate and call components such that replacing the component doesn’t require a recompile of the caller… or at least, not require the source code to be modified.

Think of a “plugin” where putting some code is a particular location and maybe editing a configuration file is all it takes to increase an application’s features.

The two most popular techniques for this is using Reflection and Aspect Oriented Programming (AOP). In a feeble attempt at keeping these articles short, I’m going to break this up, and discuss using Java interfaces, and then later talk more about Reflection and AOP in follow-up articles…

Interfaces

We have a few layers in loose coupling where some techniques are looser than others. The first level is using Interfaces, where instead of instantiating and calling an object directly, you use a Builder (design pattern) to instantiate an object that adheres to an interface, and then only call methods that are part of that interface. Let’s have an example, shall we?

Let’s pretend like we have a useful interface that defines a single method called “square” that computes the square of a number we give it. Something like this:

public interface PowerEngine {
     public long square (long value);
}

Now you need a factory that can determine (based on reasons unknown to the client) which class that implements this interface to instantiate and return to the client. It looks sort of like this:

public class PowerEngineFactory {
     public static PowerEngine  getEngine() {
          // Do some calculations and then
          return new PowerEngineA();
      }
}

A client would then use this code via:

PowerEngine eng = PowerEngineFactory.getEngine();
long power = eng.square(54);

What have we gained by this exercise? Well, it means that we can change an implementation of PowerEngine (even changing the name) without having to update the client. We also could have multiple implementations and have the factory figure out which would be the best response (often by reading at runtime a configuration file).

We have all used these sorts of factories as the Java API is full of them. In order to have a standard XML parsing library and yet allow anyone to implement a new version, we ask for an XML parser from a factory:

include javax.xml.parsers.*;
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();

In this case, every XML parsing library you may download and install implements this runtime factory. You can change a library implementation without altering your source code.

But doesn’t a client now depend on the factory class, i.e. PowerEngineFactory? Yes it does. It also depends on access to the PowerEngine interface code. Granted, the factory classes usually don’t change as much as the classes they return, but we still have more dependencies than we might like.

Before I talk about a more general solution using Reflection, let me clarify something:

You don’t have to actually create an interface. You could create an abstract parent and have all of the implementing classes simply derive from this parent. Now your client will be expect an object of the parent class. However, I think it is clearer as to your intentions to create an interface.

Another web page that references this entry...
Loosely Coupled Components, Part 1½
Excerpt:Continuing my discussion of integrating components by using the "Plugin Pattern".
Tracked:June 12, 2004 05:33 PM