Wednesday, September 20, 2006

Tom Ball's Hacking javac

Tom Ball posts a chok-full-of-nuts run through of the nifty javac happenings comming out of JDK6, leading to things like Sorcerer.

Normally I avoid posts which simply link to someone else (I rely on Erik's Linkblog for that beneficial service, but he's on vacation right now), but Ball is really on the ball with this one. I can't wait to try these out in a real project.

Wednesday, September 13, 2006

JPMorgan Investment Bank

I've been hired on this week to a permanent position with JPMorgan Investment Bank—no more contracting for me.

It's a double pleasure: I've been picked by a team with former ThoughtWorkers, an all-agile team. After getting some preliminaries out of the way, today I'll dial in for my first daily standup in several years.

I was just reading Tim Ottinger in More Work? discuss some of the benefits of agile development. It's great to see a smart place like JPMorgan with agile teams and a management that believes in its staff.

Wednesday, September 06, 2006

The continuing influence of Smalltalk

My friend Paul Holser likes to point out to me how great Smalltalk is. Just this past weekend he and I were chatting about it at the Rice's opening game (we beat the spread).

Lo and behold, why the lucky stiff mentions on 06 Sep 2006 at 13:17 (emphasis mine):

So, Matz cites four reasons for this decision:

  1. The spread of ActiveSupport has increased the need for strings and symbols to be united as hash keys.
  2. To address RCR 342 , which would allow sorting of symbols. (Try: Symbol.all_symbols.sort.)
  3. Smalltalk’s symbols are a subclass of string. (He adds that this is his most motivating reason to do it.)
  4. Using symbols as immediate values can cause them to venture into pointer territory, particularly on OSX .

Smalltalk never dies, it just slowly gets absorbed by languages with good taste.

Tuesday, September 05, 2006

Java applications, messaging and exceptions

On and off I have looked at messaging for Java applications as an alternative, more loosely coupled design pattern. Particularly for smaller applications messaging has some interesting solutions in lieu of other approaches.

Take the event listener model for AWT/Swing. Each component is responsible for maintaining its own listener event list, and each listener is responsible for finding the component it wants to get events from. This is, of course, the Observer pattern.

I want more decoupling. Message busses decouple this pattern by managing listeners and delivering events—I grew up calling this publish/subscribe—mixing in the Mediator pattern models the bus.

Channels and Subscribers

I'm going to call the bus a channel. There are many common vocabulary choices for the kind of simple message bus I have in mind, and channel is the one I used most with Gregory Hohpe who introduced me to this design. Start with the channel interface:

public interface Channel {
    void subscribe(Object subscriber);
    void unsubscribe(Object subscriber);
    void publish(Object message) throws Exception;
}

Choices, choices. Most messaging interfaces I see use a topic text to distinguish messages when publishing. But like the AWT/Swing event system, I prefer objects so that I may use inheritance to narrow or widen the scope of events I receive. Subscribers receive any intersection or union of message types they want using simple method overloading. For example:

interface BobTheBuilder {
    void onMessage(CanHeFixItRequest message);
    void onMessage(YesHeCanDispute message);
}

class MessageLogger {
    public void onMessage(Object message) {
        SomeLogger.logMessage(message);
    }
}

MessageLogger subscribes to all possible message types planning to ambitiously log everything. BobTheBuilder is only interested in requests to fix something or in criticisms of his abilities.

Supporting the union of disjoint message types explains why subscribe(Object):void and unsubscribe(Object):void take object arguments rather than using a Subscriber interface. Sketch out what Subscriber might look like with typed messages:

interface Subscriber<T> {
    void onMessage(T message);
}

This works great is a subscriber wants a single type of message, but Java does not support classes implementing the same interface multiple times—generics does not produce different interfaces:

interface IllegalJavaSubscriber {
        implements Subscriber<String>, Subscriber<Integer> {
    // Will not compile.
}

And the lack of typed interfaces for subscribers implies that the signature for onMessage(Object):void cannot narrow either. What to do? The only option is reflection. So I reflect for "onMessage" methods with the correct signature and handle overriding and overloading in the bus.

All in all I get a lot of flexibility for very little work by subscribers using the bus.

Exceptions

But what of exceptions? I realized, given the inheritance of message types, that I could simply publish exceptions as messages, same as any other type. Exception handlers simply subscribe to messages:

class ExceptionLogger {
    public void onMessage(final Exception e) {
        SomeLogger.logException(e);
    }
}

This is akin to how AOP works but without the extra syntax or new language to learn. The try/catch normally in each subscriber for logging exceptions is gathered together into the message bus with pseudo-code akin to:

for (final Subscriber subscriber
        : getSubscribersForMessage(message))
    try {
        invokeOnMessage(subscriber, message);
    } catch (final Exception e) {
        this.publish(e); // I am a channel
    }

This simplicity is very appealing, but it leaves out an interesting possibility: that subscribers could try redeliving a message to just the failed cases. Adding one more reflected method adds this option:

class SystemMonitor {
    public void onMessageException(Exception e,
        Object subscriber, Object message) {
        fixSystem(); // magic
        retryMessage(subscriber, message); // more magic
    }
}

In principal a subscriber could republish using the signature after fixing some broken part of the system. It would also make logging more informative.

Active Messages

Using pure reflection opens up another design choice, active messages. Simply having messages themselves provide an onMessage method and subscribe to the channel. Messages can publish themselves. As clever as this seems, it does leave me in fear of maintaining someone else's system years hence in which the entire thing is a ball of spaghetti with messages and subscribers calling hither, thither and yon.

Debugging is a problem with systems like this. YMMV.

Code

Some simple code illustrating this post.