|
|
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.
|
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). ![]() 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… InterfacesWe 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 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. 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. Thought originally posted on Tuesday, 18 May 2004
© 2004-2005, Howard Abrams • Except where otherwise noted, all original content is licensed under a Creative Commons License (see details). Another web page that references this entry...
Loosely Coupled Components, Part 1½
|
|||||||||||
|
||||||||||||