In testing programs, how do you meet the
tough challenge of simulating outside resources and library connections?
Component-based programming and decoupling package dependencies may be
the answer. Often touted as a means of facilitating code reuse,
component-based software development also makes for more testable code.
Eric Allen illustrates this concept of programming with examples from
Jiazzi, a powerful, free tool for component-based programming using the
Java language. Share your thoughts on this article with the author and
other readers in the discussion forum. (You can
also click Discuss at the top or bottom of the article to access the
forum.)

One issue that comes up again and again in test-first programming is
that many parts of a program seem impossible to test automatically. In
particular, programs that make heavy use of outside resources and
libraries seem hard to test because there's no good way to simulate the
program's connections to these outside resources.

However, although such programs can be hard to test with Java code
alone, there is a style of programming (with development tools) that
addresses this problem -- component-based programming.

Conceptually, these units of distribution correspond roughly to Java
packages. However, packages in the Java language are quite limited
in that they aren't decoupled from one another. The classes in each
package are hardwired to the packages that they import (because they must
refer to these packages explicitly).

Because the packages aren't decoupled from each other, it's difficult
to uniformly replace package references in a program with other package
references that provide the same functionality.

Also, separate development teams may accidentally use overlapping
package names, causing trouble when teams try to use each other's
packages. To ensure distinct package names, Sun has strongly urged the
convention that each development team use the reverse of its Internet
address as a prefix to all packages that the team develops. This
convention is often followed, but not always.

Still, even if the package-naming convention were followed perfectly,
there are other reasons programmers would want to decouple components from
one another. One reason is that we can test the components much more
effectively -- we'll explain this as we talk about a tool for
component-based programming, the Jiazzi component system.

Jiazzi: A component system for the Java
languageOne promising system for component-based
programming in the Java language that offers full compatibility with the
JVM and complete decoupling of components is Jiazzi, a development project
from the computer science department at the University of Utah. This
system allows programmers to superimpose components and wire them together
atop existing Java code. No modifications of the Java language, or the
JVM, is required.

... a system that enables the construction of [adds support
for] large-scale binary components in Java. Jiazzi components can be
thought of as generalizations of Java packages with added support for
external linking and separate compilation. Jiazzi components are
practical because they are constructed out of standard Java source code.
Jiazzi requires neither extensions to the Java language nor special
conventions for writing Java source code that will go inside a
component. Our components are expressive because Jiazzi supports cyclic
component linking and mixins, which are used together in an open class
pattern that enables the modular addition of new features to existing
classes.

The current implementation of Jiazzi integrates into the Java platform
using a linker (for manipulating components) and a stub
generator (to allow Jiazzi to be used with normal Java source
compilers). Components in Jiazzi contain, import, and export Java classes
and the Java platform's in-language support for inheritance can be used
across component boundaries. Besides being expressive, the components are
robust -- the implementation and linking of a component can be separately
type checked.

Watch it decouple
componentsTo see how Jiazzi decouples components, let's
consider a short example of a Java package, view, that makes
use of the GUI library package. We'll call this package
toolkit. To refer to all classes in the package, we would put
an import statement at the top of the source files in our package:

package view;
import toolkit.*;
...

Normally, this would tie the view package to the
toolkit package. But imagine that we wanted to compile this
source file without nailing down which package we're actually importing.
Instead of hardwiring the connections between the toolkit and
view packages, we can envision defining a function over
packages that takes a toolkit package and returns a
view package that depends on it. In Jiazzi, these functions
are called units.

Units are like LEGO bricks; they can be snapped together to create a
program. If we view units as functions, we can say that Jiazzi provides
for functional composition. Every unit takes one or more packages
with specified "package signatures" and exports one or more packages,
again with a specified signature.

Package signatures are like types; they constrain the shape of a
package. A package signature would define the classes expected in a
package, the method signatures of those classes, and so on. The signatures
of the exported packages may depend on those imported.

There are two types of units:

Atoms, which are simple mappings between packages

Compounds, which are compositions of other units

Atoms describe the packages they import and export directly. Compounds
inherit the imported and exported packages from the units they compose. If
we view units as LEGO bricks, atoms are individual LEGO bricks and
compounds are structures built from multiple LEGO bricks.

Units are described in separate files with a special specification
language. This language assigns names to the packages input and output by
a unit. For example, here is a simple atomic unit that takes in a
toolkit package and outputs a view package:

atom app_view {
import toolkit: toolkit_s;
export view: view_s;
}

This unit is named app_view. It assigns the name "toolkit"
to the package it imports. This package is declared to fit a particular
package signature called toolkit_s. The package exported by
the unit is called view and is declared to fit the signature
view_s.

First, a set of signature and unit definitions are fed to the Jiazzi
stub generator, which then generates stub class files for all of the
classes imported in the signature of any unit given to it.

These class files are then used by a conventional Java compiler to
compile the source files corresponding to the classes exported by the
units given to the stub generator.

After compilation of the sources files, the Jiazzi unit linker
checks that the resulting class files match the class signatures
declared in the original units. This is necessary because:

Any third-party compiler can be used with Jiazzi

Jiazzi never examines the Java source files

(By the way, notice that Jiazzi's approach of never actually viewing
the Java source code is a big win. It allows us to use Jiazzi with
compilers for non-Java languages targeted for the JVM, such as Jython,
JSR-14, and NextGen. In fact, Jiazzi itself is written in JSR-14.)

After checking, the component linker generates a JAR file for each unit
given to it. This JAR contains the compiled sources and stubs, as well as
the signature information, as metadata. These JARs can then be linked
together by feeding them to Jiazzi alongside appropriate compound
units.

Units can also be linked online by a special class loader. However,
because the stub classes that the units were compiled against are not
available, type checking must be done in the class loader as an
"incremental whole-program analysis." In fact, at present, Jiazzi
programmers must use a combination of offline and online linking, as many
classes in the standard Java libraries can be linked to only through the
class loader.

Another limitation of the current system is that renaming interferes
with JNI and the reflection libraries. In particular, native methods are
not renamed, as they are written in C code. As a result, many of the class
libraries (which rely heavily on JNI and reflection) can't be repackaged
as Jiazzi components.

As noted, compound units describe connections between other units. The
linkages are in relation to the bound names of the imported and exported
units of the compound; the linked units are completely unaware that they
are linked (the linker ultimately macro-expands these compound units into
atoms).

In this way, we can create and distribute JAR files for a program in
such a way that we could swap new packages in and out with a simple
recompilation. Not a single line of Java source code need be touched.

Additionally, other users of Jiazzi can develop against the classes
provided by our program before our JAR file is available; all they would
need are the package signatures corresponding to what we export. And their
extensions would link just as well to any other implementation of that
package signature.

Unit testing and
JiazziComponent-based programming offers big advantages.
The most often touted advantage is that components allow for greater code
reuse. Off-the-shelf components can be distributed separately and plugged
into new applications at will. But this style of programming also allows
for much more effective unit testing.

During testing, the constituent components of a program can be linked
with special "mock" components whose classes simply record the actions of
the components they test. In essence, these mock components serve a
similar role to that of Recorders (see "Recorders test for proper method
invocation" in Resources),
but at the component level.

The tested components are like Cartesian "brains in vats"; they can't
tell the difference between being wired to mock components or to real
components. For example, in our sample application earlier, we could write
a special test_app compound that wires our
app_view unit with a test_toolkit unit, like
this:

Package test_toolkit would export a package of the same
signature as toolkit, but this package would consist solely of mock
objects that fooled app_view into thinking that it was linked
to a true toolkit. These mock objects could record the actions performed
by app_view, as these recordings could be checked in the unit
tests.

Compare this system with the Java package system, where every source
file must explicitly state the packages it imports. In the Java package
system, the only way to fool a whole package into linking to a test
package would be to edit all of the source files and recompile. That
procedure doesn't really lend itself to automated testing.

Unfortunately, because Jiazzi (quite reasonably) can't handle
reflection or JNI, and because these facilities are used extensively by
many of the built-in Java APIs, the existing API packages can't be
converted into Jiazzi components. But if they could, we'd be able to
perform much more powerful tests over our programs. For instance, a
program that used the Swing API could be wired to a mock Swing component
during testing that ensured all of the appropriate API calls were made
without actually trying to draw graphics objects. In a similar manner, we
could test interaction with the java.io package, Java3D,
JDBC, RMI, and any other API where the performance or nature of the
functionality makes clients difficult to test.

Okay, nice dream, right? But even if reflection and JNI prevent us from
making existing APIs into first-class Jiazzi units, there is a potential
compromise.

Although connections between the existing APIs couldn't be decoupled,
connections from new units to these APIs could be. In essence, the APIs
could be bundled in special units that only exported classes; their
imports would still be hardwired through the existing Java package system.
Doing so would give us 99 percent of the functionality we'd have if these
APIs were bona fide units; the only programmers that wouldn't be happy
would be those who would like to build third-party replacements to the
existing APIs.

Hopefully, Jiazzi evolution will move in this direction, or on a
similar path that allows us to use it with the existing APIs. In the
meantime, it still provides a very powerful mechanism for testing packages
that don't use reflection or JNI.

Decoupling the pastThe
original motivation behind Jiazzi was as a mechanism for feature
extensibility -- decomposing a design into multiple features (in which
each feature is put in a separate component). Component-based programming
advocates envision a future in which developers build programs from
off-the-shelf components provided by component vendors. Components with
common signatures could be swapped in and out like car parts.

Whether or not that comes to pass, there are big advantages to
component-based programming even without a ubiquitous component software
market. In particular, this style of programming allows for much more
effective unit testing.

As we've shown, component-based programming with Jiazzi provides a very
powerful way to test program components, and it works with existing Java
(or Jython, or JSR-14) source files. We can all benefit from this powerful
tool. It and others like it are an essential part of test-oriented
programming.

Next time, I'll discuss Jam, an extension of the Java language that
allows for mixin-based programming. Just as Jiazzi provides a way to
decouple package dependencies, mixins provide a way to decouple class
dependencies. As you might have guessed, mixins provide us with yet
another powerful mechanism for testing a program.

Find hundreds more Java technology articles and tutorials on the
developerWorksJava technology
zone.

About the
authorEric Allen has a bachelor's degree in computer
science and mathematics from Cornell University and is a PhD
candidate in the Java programming languages team at Rice University.
Before returning to Rice to finish his degree, Eric was the lead
Java software developer at Cycorp, Inc. He has also moderated the
Java Beginner discussion forum at Javaworld. His research concerns
the development of semantic models and static analysis tools for the
Java language, both at the source and bytecode levels. Eric is the
lead developer of Rice's experimental compiler for the NextGen
programming language, an extension of the Java language with added
language features, and is a project manager of DrJava, an
open-source Java IDE designed for beginners. Contact Eric at eallen@cs.rice.edu.