Wednesday, January 26, 2005

Read-only properties in Java

C++ has the advantage over Java of supporting operator overloading. In particular, this makes straight-forward to implement read-only and write-only fields (data members in C++ parlance) that actually call back to methods (member functions) when accessed. C# has this feature as well. You cannot do that in Java, but you can at least provide a form of read-only fields.

Traditional Java uses bean-style getters and setters for field access, but there is a more elegant solution for data transfer-style objects:

public class ReadMe {
    public final String title;
    public final String body;

    public ReadMe(final String title, final String body) {
        this.title = title;
        this.body = body;
    }
}

That's it! This is yet another interesting use of the final keyword. The class fields are public, but because they are marked final, they cannot be modified once set and final fields must be initialized during construction. This prevents tampering, and makes the fields read-only. Using ReadMe is trivial:

public void displayReadMe(final ReadMe readMe) {
    createDialog(readMe.title, readMe.body).show();
}

Trivial — no getters or setters required. This idiom is flawed if you need to update the object, however, but field setters have plenty of drawbacks so this complaint is a mild one.

Monday, January 24, 2005

Throwing complex exceptions

In Java you sometimes have complex exceptions whose creation requires more than just a call to new. In those cases, I like to use a helper method to separate the the construction of the exception from the code which might throw the exception. (In fact my taste is to use such a helper anytime the exception is not ready in a single line of code. Sadly, IOException is such an exception when it has a cause: it is missing the full set of constructors that other descendents of Exception have.)

For such times which of these two snippets is preferred?

public void work(final Queue<PieceOfWork> workQueue)
        throws IOException {
    if (!doWork(workQueue))
        throw createWorkException(workQueue);
}

private WorkException createWorkException(final Queue<PieceOfWork> workQueue) {
    final WorkException e = new WorkException(getJobId());

    for (final PieceOfWork piece : workQueue)
        e.addPieceOfWork(piece);

    return e;
}

Or:

public void work(final Queue<PieceOfWork> workQueue)
        throws WorkException {
    if (!doWork(workQueue))
        throwWorkException(workQueue);
}

private void throwWorkException(final Queue<PieceOfWork> workQueue)
        throws WorkException {
    final WorkException e = new WorkException(getJobId());

    for (final PieceOfWork piece : workQueue)
        e.addPieceOfWork(piece);

    throw e;
}

Until recently I thought there was little difference between them but have changed my mind. Why? The first case is easy for static analysis tools to identify that there are two code paths, one of which throws an exception. The second case requires that the tool descend into throwWorkException and work out that one of the code paths throws an exception.

Although this is not much to ask of many of the more sophisticated static analysis tools, it is too much to ask of most of the tools bundled with common Java editors. IntelliJ IDEA, for example, does not pick up on this as it analysis your code as you type: it makes the sensible tradeoff of performance for completeness.

In fact, shallow static analysis is the reason javac flags this as an error:

public boolean checkCondition()
        throws SomeException {
    if (!cannotProceed())
        throwSomeException();
    else
        return true;

    // Missing return statement
}

Sad code, yes, but not uncommon, especially when the branches get very complicated so that it is not so obvious that they could be simplified.

Lastly, keeping the throw statement as close as possible to where the condition failed helps the most common static analysis tool of all: the human eye. When quickly browing others code, it is easy to miss the true code flow without the helpful throw keyword staring one right in the face.

Thursday, January 20, 2005

Whither aspectj?

This is cool news: the AspectJ and AspectWerkz projects are merging with annotations coming to the fore. I am very curious to see how this will work with JDK 5's apt tool. Apt (annotation processing tool) lets you process annotations at compile-time and extend the compiler with new syntax (as long as that syntax is annotations). I hope aspectj takes advantage of this clever system and uses annotation processors; a cursory look through the compiled jars doesn't seem to indicate that from the class names. It's a shame aspectj's download page does not provide the source to go with the binary installer.

Sunday, January 16, 2005

Wrong method with reflection

Try this:

public Method getUnaryMethod(final Class clazz,
        final String name, final Class parameterType)
        throws NoSuchMethodException {
    return clazz.getMethod(name, parameterType);
}

Looks easy, doesn't it? But:

private static class Overloaded {
    public Class foo(final Number number) { return number.getClass(); }
    // public Class foo(final Integer integer) { return integer.getClass(); }
}

void void testGetUnaryMethod() throws Exception {
    final Class expected = Integer.class;
    final Class actual = getUnaryMethod(Overloaded.class,
            "foo", expected).getParameterTypes()[0];

    assertEquals(expected, actual);
}

The test throws! To pass the test, uncomment the second definition of foo. Unfortunately, I'm working on a dispatch system and this sort of thing is death. Why? Because I cannot repeat with reflection this simple call:

new Overloaded().foo(new Integer(3));

There is a solution, though, replace getMethod with:

public static Method getMethod(final Class clazz,
        final String name, final Class parameterType)
        throws NoSuchMethodException {
    for (Class c = parameterType; null != c; c = c.getSuperclass())
        try {
            return clazz.getMethod(name, c);

        } catch (final NoSuchMethodException e) { }

    return clazz.getMethod(name, parameterType);
}

I look up the inheritance tree for parameterType until I find the first exact match via reflection and return that method. The catch block just lets me retry the lookup one branch higher in the tree. If I exhaust the tree, there is no match even with inheritance, in which case I retry the original lookup so as to throw the same exception as Class.getMethod(String, Class[]) would.

Now I can dispatch dynamically with reflection the same as would the Java runtime. The only drawback is that this simple algorithm only works to vary a single parameter type. For true multiple dispatch, I need a better algorithm to vary more than one parameter type and detect ambiguities: this would let me work methods with more than one argument.

Useless overload

Gotcha! — That's how I felt. I changed code like this:

final Worker worker = new Worker();
final Implement hoe = new Hoe();

worker.work((Hoe) hoe);

To remove the "obviously" useless cast. Well, no, not useless at all. I had overlooked Worker.work():

public class Worker {
    public void work(final Implement o) {
        // Generic work
    }

    public void work(final Hoe hoe) {
        // First do generic work
        work((Implement) hoe);
        // Now do hoe-specific work
        hoe.work();
    }
}

Argh! Of course, there are several much better ways to do this, and I could have changed the declaration of hoe instead of removing the cast. Putting the onus on the caller to pass in the right type of object is just grotesque. And by removing the cast, I broke the code.

I congratulate whomever devised that nasty trap, requiring two useless casts to work correctly and splitting them between the caller and the method no less! Unfortunately, it was purely accidental on their part.

Next time, please code this:

public interface Implement {
    public void work();
}

public class Worker {
    public void work(final Implement implement) {
        // First, generic work
        // Lastly, implement-specific work
        implement.work();
    }
}

Or, if you prefer, make Implement a class with a default, empty work() method. Just something that avoids uselessly useful casts and that requires ESP from the caller.

Thursday, January 13, 2005

The little nullity and a little final

Waldura writes a wonderful article on the final keyword in Java. For me also final is possibly my favorite keyword in the language. What I like best of all about it is its interaction with null. Consider this:

public class Mandatory {
    private final Law law;

    public Mandatory(final Law law) {
        if (null == law)
            throw new NullPointerException();

        this.law = law;
    }

    public Law getLaw() {
        return law;
    }
}

Here law is mandatory, that is, the class never works right without a law. Note the idiom in the constructor. Once the constructor finishes, the class is guaranteed to be null-proof: there's no setter to foul it up; the field is marked final so it won't even compile if you forget to set law in all constructors. No one calling getLaw() need ever check it for nullity. I cannot tell you how tired I get of fixing code where the author does not understand the frequent problems null generates!

And the other way with an optional field instead of mandatory as above:

public class Optional {
    private Virtue virtue;

    public Optional() {
    }

    public Optional(final Virtue virtue) {
        setVirtue(virtue);
    }

    public void setVirtue(final Virtue virtue) {
        this.virtue = virtue;
    }

    public boolean hasVirtue() {
        return null != virtue;
    }

    public Virtue getVirtue() {
        if (null == virtue)
            throw new NullPointerException();

        return virtue;
    }
}

See how much more complicated Optional is than Mandatory? Once you have optional members of a class, it drastically complicates matters. There are extra constructors (and I'm ignoring the whole notion of default values). There is the hasX()/getX() pair to catch accident use of null as early as possible. There is the setter. And we have lost the benefit of final.

The lessons? Avoid optional members (this is quite different, by the way, from the lazy evaluation idiom). Combine final with preventing nullity. The Java language encourages this with the elegance of the mandatory-field class v the clumsiness of the optional-field class.

Write elegant code, not clumsy code.

UPDATE: Reedited for clarity; too much late-night fractured grammar.

Saturday, January 08, 2005

Do or die

I believe that the Do-or-die principle is the strongest protector of good software, and the greatest preventative against mystery bugs, convoluted logic and tortuous coding. What do I mean?

Do-or-die is simple: either an operation succeeds or it raises an exception. When you call a do-or-die method, any normal code path relying on the results of that method have a guarantee for sanity—there are no problems to check for or deal with in the normal code path. The abnormal code path coping with the raised exception handles all problems. (Contrast this with languages lacking exceptions.) This means:

  1. Any procedure always returns void; no boolean returns that require checking for success or failure. Just call the procedure and be done with it.
  2. Any function always returns a valid object; no null returns that require nullity checks. Just capture the return and use it as expected.

Because of do-or-die, tremendous amounts of work, thinking, testing, coding and bug hunting are eliminated. Code is vastly more readable without a thicket of checks, nexted if/else blocks and null handling. Clarity and sanity is a natural product of do-or-die. I can think of no other idiom with as high a payoff in simplicity of notion to size of benefit.

Friday, January 07, 2005

Decreasing functor syntax in Java

Functor, closure, functional, operator, executor: there are many names in Java for the same thing, a class which encapsulates a single generic operation than can be handed around like the unsyntactic anonymous function available in other languages.

For a while, I've used some variation of this model:

public interface Closure {
    void execute();
}

Typical use:

new Closure() {
    public void execute() {
        System.out.println("Ni!");
    }
}

This is perfectly adequate when you create such a thing and pass it around. But what if you are looking to use it immediately? I sometimes see this:

new Closure() {
    public void execute() {
        System.out.println("Ni! Ni!");
    }
}.execute();

The example is contrived, but the principal is easy to grasp: there is a shorter way to do this. Try instead:

public abstract class ImmediateClosure {
    protected ImmediateClosure() {
        execute();
    }

    public abstract void execute();
}

new ImmediateClosure() {
    public void execute() {
        System.out.println("Ni! Ni! Ni!");
    }
};

Shorter. That's all I'm saying.

Tuesday, January 04, 2005

Testing without tests

Like some horrible nightmare come back to haunt the daytime, I'm working on an extensive, mixed-language code base lacking unit tests. XP likes to promote courage—the courage to make changes—, but without unit tests I feel like a tight-rope walker with no net to catch me when I fall. And sure enough, I fell this past week.

Our code base has some serious poor design decisions, many of which are old and embedded in the psyches of existing staff. No one defends the errors, but everyone is afraid to cut them out for fear that the operation may be a success, but the patient dies anyway. I began some cutting last week, trying to untagle a weave of deeply-nested if/else branches, protected data members, fake data objects and everpresent tests for null. Every single one of these is a bad code smell.

It comes as no surprise that I failed to repair all the damage I caused in my changes given that there were no unit tests for the affected code. I added unit tests where I worked directly, but that left large swaths of code untested elsewhere, much of it lurking and unseen in unrelated (but actually related) sections of our system. I've since added more tests and fixed the resultant defects, but in the meanwhile we had about a week of failed Q/A testing in areas no one thought had changed.

XP also eschews code ownership and programmer ego, so I owned up quickly in a public email that I thought I may have caused the problems with my changes, and that I was looking for someone to review code with me to find the trouble spots. This did get one senior programmer to review one of my changed files and to note that he could see nothing wrong with it, but it also prompted him to publically rebuke me when I asked him for a code review of my new changes that fixed one of the problems. He was afraid his name would be tarred by my mistakes. This makes for a difficult environment to work in.

Courage, I remind myself, courage. And more unit tests.

Wednesday, December 29, 2004

Using apt

While exploring the new JDK 5 tool apt (annotation processing tool), I figured out how to write new source code that is compiled into my build tree along side my regular Java sources. Here is a trivial example.

First, I need an annotation processing factory (I ignore imports and such throughout):

public class MyAnnotationProcessorFactory
        implements AnnotationProcessorFactory {
    public Collection supportedOptions() {
        return Collections.emptySet();
    }

    public Collection supportedAnnotationTypes() {
        return Collections.singleton(
                getClass().getPackage().getName() + ".*");
    }

    public AnnotationProcessor getProcessorFor(
            final Set atds,
            final AnnotationProcessorEnvironment env) {
        return new MyAnnotationProcessor(atds, env);
    }
}

Second is to have an annotation processor:

public class MyAnnotationProcessor
        implements AnnotationProcessor {
    private final Set atds;
    private final AnnotationProcessorEnvironment env;

    MyAnnotationProcessor(final Set atds,
            final AnnotationProcessorEnvironment env) {
        this.atds = atds;
        this.env = env;
    }

    public void process() {
        for (final AnnotationTypeDeclaration atd : atds) {
            for (final Declaration decl
                    : env.getDeclarationsAnnotatedWith(atd)) {
                final String typeName = decl.getSimpleName() + "Example";
                final String fullTypeName = getPackageName() + "." + typeName;

                try {
                    final PrintWriter writer
                            = env.getFiler().createSourceFile(fullTypeName);

                    writer.println("package " + getPackageName() + ";");
                    writer.println("public class " + typeName + " {");
                    writer.println("}");

                } catch (final IOException e) {
                    throw new RuntimeException(fullTypeName, e);
                }
            }
        }
    }

    private String getPackageName() {
        return getClass().getPackage().getName();
    }
}

Last is to tell apt how to fit it all together (I'm using a Maven-style layout):

apt -cp target/classes
    -s target/gen-java -d target/gen-classes
    -target 1.5 -factorypath target/classes
    -factory MyAnnotationProcessorFactory
    src/java/AnnotatedExample

When I run the apt command, given suitable annotations in AnnotatedExample, it pulls them out, instantiates my annotation processor via my factory, and hands them to process() therein. The key is to use com.sun.mirror.apt.Filer, a class in $JAVA_HOME/lib/tools.jar. There are no online javadocs that I have found yet. Here is what the JDK 1.5.0_01 sources say about the Filer interface:

This interface supports the creation of new files by an annotation processor. Files created in this way will be known to the annotation processing tool implementing this interface, better enabling the tool to manage them. Four kinds of files are distinguished: source files, class files, other text files, and other binary files. The latter two are collectively referred to as auxiliary files.

There are two distinguished locations (subtrees within the file system) where newly created files are placed: one for new source files, and one for new class files. (These might be specified on a tool's command line, for example, using flags such as -s and -d.) Auxiliary files may be created in either location.

During each run of an annotation processing tool, a file with a given pathname may be created only once. If that file already exists before the first attempt to create it, the old contents will be deleted. Any subsequent attempt to create the same file during a run will fail.

My next step is to glue velocity into my processor so I can use templates for writing the new Java sources.

Tuesday, December 28, 2004

The future in futures

Brian McCallister has started a great set of posts on futures. This fits in perfectly with my work with Gregor Hohpe on Mercury, a light-weight messaging library for Java. Brian explains futures:

Futures are really nice conceptually, and provide for much more natural and easy to use concurrent design than Java style threading and monitors. It relates to a lot of functional programming concepts, but the key idea is that a future represents an evaluation which has not yet occured. Maybe it is being lazily evaluated, maybe it is being evaluated concurrently in another thread.

Java has no futures, but I do fake closures using reflection and a sort of distended proxy. The core of Mercury is that when code publishes a message to a channel, it is not immediately delivered. Instead, the channel records an activation record (binding) and begins reordering the records before activating the bindings. This lets Mercury have breadth-first message delivery instead of depth-first, and circumvents the effects of using a call stack in a messaging system.

Gregor's excellent Enemy of the State post describes the thinking in more detail along with some ramifications. I'm just the humble mechanic who coded the library. :-)

UPDATE: I just got an anonymous comment pointing me to java.util.concurrent.Future. Zowie! That's a cool thing to find.

Sunday, December 26, 2004

Using JDK 5 varags for testing

One JDK 5 feature I have started using to clean up my testing is varargs, the ... (or … for the entity-aware). It is particularly elegant to turn this:

public void testWidgetProcessor() throws Exception {
    final Widget expected1 = createWidget(), expected2 = createWidget();

    processor.swallow(new Widget[]{
        expected1,
        expected2
    });

    assertWidgetsGained(new Widget[] {
        expected1,
        expected2
    });
}

Into this:

public void testWidgetProcessor() throws Exception {
    final Widget expected1 = createWidget(), expected2 = createWidget();

    processor.swallow(expected1, expected2);

    assertWidgetsGained(expected1, expected2);
}

And even better:

public void testWidgetProcessorHandlesTrivialCase() throws Exception {
    assertWidgetsGained(); // nothing swallowed, nothing gained
}

XOM Design Principles

A very, very interesting article, XOM Design Principles, on Java library design. What took me particularly off-guard was the preference for classes over interfaces. The argument over this point presents much to digest.

Sunday, December 19, 2004

What are Java annotations?

This must be described elsewhere, but a quick Googling didn't give it to me. A little experimentation reveals to me that JDK 5.0 annotations are dynamic proxies under the hood.

To find this out, I made an annotation named @annotate and exammined annotation.class; it revealed itself to be an interface. I then decorated a method with @annotate, got the Method with reflection, pulled the appropriate annotation class off with getAnnotation(annotate.class).getClass() and examined that: dynamic proxy, $Proxy3(java.lang.reflect.InvocationHandler).

I wonder how I can use this knowlege for some real Java-fu.

UPDATE: An even stronger answer: Proxy.isProxyClass(Class) returns true on the method annotation class, and the proxy invocation handler is a sun.reflect.annotation.AnnotationInvocationHandler. Good thing Sun provides source for the non-public bits.

Saturday, December 18, 2004

A taste of things to come

Now to make it work!

/**
 * Marks a method with a <em>pre-condition</em>.  The required annotation
 * {@link #value()} is a <code>boolean</code> condition.  The optional
 * {@link #message()} is used in {@link DBCException} if the condition
 * fails.
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface pre {
    boolean value();

    String message() default "";
}

/**
 * Marks a method with a <em>post-condition</em>.  The required annotation
 * {@link #value()} is a <code>boolean</code> condition.  The optional
 * {@link #message()} is used in {@link DBCException} if the condition
 * fails.
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface post {
    boolean value();

    String message() default "";
}

/**
 * Marks a method with an <em>invariant</em>.  The required annotation
 * {@link #value()} is a <code>boolean</code> invariant.  The optional
 * {@link #message()} is used in {@link DBCException} if the invariant
 * fails.
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface inv {
    boolean value();

    String message() default "";
}

UPDATE: I'll have to think about this longer. Turns out that annotations only accept constants or expressions which evaluate to constants. A constant pre-condition isn't very interesting.

Friday, December 17, 2004

Looking up the location of a class file

IBM's JAR Class Finder reminds me of a snippet of utility code I wrote for PCGen which used a clever trick to find the location on disk of the definition for a given class, either a jar or a directory in the classpath:

new File(clazz.getProtectionDomain().getCodeSource().getLocation().toURI().normalize())

The only drawback: for the JDK itself the protection domain has a null code source. Since Class.getProtectionDomain() relies internally on a native method to create the protection domain, I'm unsure if this is a bug or intended behavior. It certainly isn't documented in the javadocs. I consider this a bug, but others disagree and it has changed between JDK versions.

Thursday, December 16, 2004

Clever IDEA

I just noticed very clever behavior by IntelliJ IDEA 4.5.3 on Windows. I ran a junit test that crashed the test JVM from badly behaved JNI code. Unfortunately, this caused the JVM for IDEA itself to eventually exhaust memory and crash. IDEA handled this well, informed me of the problem, and gracefully shutdown.

The cool part: when I launched it again, it ran the console window for the LAX launch wrapper. Normally this does not appear so that you just have the main application window, but the console emits all sorts of interesting information useful to someone developing IDEA. Presumably, had the crash I mentioned been IDEA's fault, I could use that information to help IntelliJ fix the bug.

Further, I closed IDEA normally and relaunched it. This time it come up normally with no extra console window. The console window feature is only triggered by a crash in IDEA. Nifty!

Wednesday, December 15, 2004

Messaging with annotations

I'm working on a talk for SD West 2005 with a former coworker, Gregor Hohpe of ThoughtWorks. We coded a simple Java messaging system for single VM apps. Most messaging systems are based on messages segregated by subject, usually a String field. Our system though is type-based. Messages implement (or extend) Message, and receivers provide methods receive(Message) to receive published messages.

The dispatch loop makes extensive use of reflection to find a "best matching" method. If you have:

public class FooReceiver extends Receiver {
    public void receiver(final Message message) { }

    public void receiver(final FooMessage message) { }
}

Then if a FooMessage (or a subtype) comes along, the better matching method receives the message, otherwise the more general method does.

But I have found a better way: annotations :-) Consider:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MessageHandler {
    Class[] value();
}

This bit of annotation magic lets me say this in my receiver class:

public class FooReceiver {
    @MessageHandler({Message.class})
    void receiveAllTypes(final Message message) { }

    @MessageHandler({FooMessage.class})
    void receiveFooTypes(final FooMessage message) { }
}

Now if a FooMessage comes along, both methods see the message: logically, there is no method overloading to consider since they are differently-named methods. But this has several other advantages:

  • No need to extend or implement anything; just annotate the methods
  • Methods can have better names than just receive; it's the annotation, not the name, which counts
  • Interestingly, you can write methods to handle disjoint types:
public class DisjointReceiver {
    @MessageHandler({FooMessage.class, BarMessage.class})
    void handleEitherFooOrBarType(final Message message) { }
}

Nifty — there is no need for FooMessage or BarMessage to be related types. In fact, to carry the disjunction one step further, I could dispense entirely with the Message class! Hmmm...

UPDATE: I fixed the bad links. That's what I get for blogging while woozy with flu.

Maven and test cases

I have a problem with maven I am hoping someone knows the best solution to. As is typical with Java projects using maven, I have separate src/java and src/test trees and they compiles to build/classes and build/test-classes, respectively. When I build a distribution jar, maven zips up build/classes into the jar (along with LICENSE.txt and any resources). This much I know and appreciate.

However, my project uses JUnit for testing, so I have *Test classes, one for each class under test. And my project provides *TestCase base classes for other test classes to extend. The test case classes add functionality to junit.framework.TestCase. These live under the src/test tree since they are only used for testing, and they are dependent on junit-3.8.1.jar. Of course, they compile to build/test-classes.

But since the dist goal only packages up build/classes, the test case classes do not become part of my distribution jar. And I want to package them for distribition. Oops.

For now, I've moved the test case classes from src/test to src/java so that maven will bundle them in the distribution jar, but I feel awkward doing that.

Is there some way to teach maven to pull src/test/**/*TestCase.java classes from build/test-classes into the distribution jar, but no other test classes?

Delegation, a problem and solution

I'm adding unit testing to existing code and encounter this problem:

public class Foo {
    private static Foo SINGLETON;
    private static Trouble TROUBLE;

    private Foo() { }

    public Foo newInstance() {
        if (null == SINGLETON) SINGLETON = new Foo();
        return SINGLETON;
    }

    public Trouble getTrouble() {
        if (null == TROUBLE) TROUBLE = new Trouble();
        return TROUBLE;
    }

    public void doSomething() {
        getTrouble().doSomethingElse();
    }
}

Callers are expected to write Foo.newInstance().doSomething(). Fair enough. For unit testing, I want to replace SINGLETON with a stub or mock object that extends Foo in setUp() and put it back to null in tearDown(). Foo is not under test, but classes I am testing call to it and I need to control the interaction.

What about TROUBLE? It is a complex object with its own behavior, so I need to stub or mock it as well. But here's the rub: I don't have control over its source. It could be a SWIG-generated wrapper for JNI, or from a third-party jar I lack the sources to. And the class looks something like this:

public final class Trouble {
    public void doSomethingElse() { }
}

Oops! No extending for me. what to do? It is time to rely on delegation.

First, extract an interface from Trouble, say Troubling, which contains all the public methods in Trouble. We cannot change Trouble to implement Troubling, but I'll overcome that in a moment.

Second, update Foo and all callers of Foo.getTrouble to refer to Troubling and not Trouble. This decouples them from dependency on Trouble.

Third, create a new class which implements Troubling and delegates to Trouble:

public class NoTrouble implements Troubling {
    private final Trouble trouble;

    public NoTrouble(final Trouble trouble) {
        this.trouble = trouble;
    }

    public void doSomethingElse() {
        trouble.doSomethingElse();
    }
}

Lastly, update Foo to use NoTrouble instead of Trouble:

public class Foo {
    private static Foo SINGLETON;
    private static Troubling TROUBLE;

    private Foo() { }

    public Foo newInstance() {
        if (null == SINGLETON) SINGLETON = new Foo();
        return SINGLETON;
    }

    public Troubling getTrouble() {
        if (null == TROUBLE) TROUBLE = new NoTrouble(new Trouble());
        return TROUBLE;
    }

    public void doSomething() {
        getTrouble().doSomethingElse();
    }
}

We're following the ancient dictum, any problem can be solved by introducing an extra level of indirection. Foo was already delegating doSomething() to Trouble; we just replaced that relationship with an extra level of delegation, Foo to NoTrouble to Trouble. Now I can mock or stub NoTrouble without needing access to Trouble.

Go have a peanut butter sandwich.

Saturday, December 11, 2004

The easy way

While updating Java code to permit replacement of one implementation of a system-wide object with another (in this case, we have a physical device which is needed for production code, but which is a problem to require for unit tests — I want to use a mock or stub implementation for testing to avoid accessing a real device)

I started down the inversion of control path and faced a daunting problem: large portions of the system needed updating to support appropriate constructors, new class members to hold the IoC objects, rewritten callers to cope with the new constructors, ad nauseum. Yikes!

What to do?

After some tinkering, I decided to give up on the "pure" solution and hack something just for the immediate problem at hand. Rather than adjust code all through out the system (and try to adjust the culture around me to accept those changes "just for testing"), I limited the scope of change to just those places which actually need a device object.

First I implemented the singleton pattern for the device class, then refactored all the users to call Device.newInstance() instead of new Device().

Next, I made sure the singleton implementation used lazy initialization:

private static Device SINGLETON;

public static Device newInstance() {
    if (null == SINGLETON)
        SINGLETON = new Device();

    return SINGLETON;
}

There's the crux: now testing code can put a stub or mock implementation into the SINGLETON field with reflection in setUp() and replace it with null in tearDown(). This ensures that tests see only a stub or mock implementation anywhere in the production code which uses a device object. And no code need know any details about who uses a device object or how.

Finally, tearDown sees to it that other tests get a real device implementation if they need one since it sets the singleton back to null (see the code above).

The only other update to the device object is to make the constructor protected so that a stub or mock implementation can extend the class.

Thursday, December 09, 2004

What is remove in a map?

While coding a utility map class I was struck by this problem: what is the meaning of remove? That is, what does does it mean to remove a key when the map has more than one value for that key? How could that happen, you ask. My map isn't the ordinary sort: it's a union map, or a view of a list of maps.

Picture a stack of maps like a column of egg cartons over which you stand. As you look down through a particular cell from above, some cartons have an egg there, some do not. My union map is as if you collapsed the stack of egg cartons. Into each cell goes some kind of combination of the eggs from the corresponding cells in the original stack. The usual rule selects the top-most egg; remove just the top-most egg, and the rule selects the next egg down in the stack of cells; if there are no eggs in any cell, the collapsed cell is also lacking.

So I am faced with the question, what does it mean to remove a key from the union map? Do I remove all eggs in the matching cell from all cartons, or do I just remove the top-most one and the cell has a new value? Either way seems to me not quite right. As a practical matter, I chose for remove to remove all values for the key in all stacked maps so that collectively they would still follow the requirements of remove in the JDK, and I provided a removeOne to remove just the top-most value. Linguistically, I'd prefer for remove to perform this function, and for a removeAll to remove the key-value pairs from all stacked maps, but that would break expectations.

Suggestions?

Friday, December 03, 2004

Reinventing Smalltalk

What a cool idea! —

But ah-hah! We do, we can use a different implementation of FunctionTable which stores the method body as a String in Derby and uses BeanShell (or Janino!) to invoke it. So a method invocation is completely configurable at runtime! Not deploy time, runtime. If you find a bug, you can fix it without a redeploy.
Yes, Virginia, there is runtime update of objects in memory. What these two have come up with is the redefinition of object methods in a running system, no restart required. There's infrastructure to build to make it happen, but the principle is demonstrated. Java is catching up with Smalltalk bit by bit.

Thursday, December 02, 2004

Have IDEA mark all qualifying variables as final

I finally figured out a trick with IDEA that I've been searching for for more than a year now. I like to mark all qualifying variables as final when I work in Java. I used to strip final as noise, but was convinced by Chapter 2[PDF] of Hardcore Java that final is a fine thing and good coding practice.

But back to IntelliJ IDEA. Marking all qualifying variables as final is a real pain. Why not have the editor do it for me? I certainly can flag unmarked variables with warnings (Settings|Errors|Local Code Analysis|Local variable or parameter can be final).

To have the editor mark all qualifying variables globally as final, run the analysis tool on a file or your whole project with Analyze|Inspect code...|Local Code Analysis|Local variable or parameter can be final, then Run.

When the results return, the left pane displays analysis problems. Expand the Local Code Analysis node, select the Local variable or parameter can be final node underneath, and push the "lightbulb" (Apply a quickfix) button. This fixes the problem for all qualifying variables all in one go. Wonderful!