Open Source, Closed Runtime

2009-03-23

As is wont to happen now and again, the other day I received an IllegalArgumentException. Dragging my carcass down the dusty stacktrace, I find the culprit:

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();

Oh boy. That makes me mad. (This actually happened weeks ago, I just now calmed down enough to write this.)

We are looking at a constructor, and we are looking at years of wasted time for mankind. Java is now thankfully open source, but this is a cause of the closed runtime syndrome, being the term I’ve decided to rant about in this post.

In all fairness, this code isn’t half bad. If you detect an illegal argument, you should throw an exception instead of continuing. Argument checking and failing fast are wise practices. But one important aspect is not handled here: Revealing which argument was the illegal one, and why. It’s not like it’s difficult; this would be enough:

    throw new IllegalArgumentException(corePoolSize + "/" +
        maximumPoolSize + "/" +
        keepAliveTime)

Using the source and the actual exception, this gives me more clues about what’s going on, without having to pull out my debugger. But we can still take another big step in the right direction. What if we were to get this information from just the exception, without the need to consult the source? Sounds utopian, but it turns out to be quite straightforward. Here’s an example:

    throw new IllegalArgumentException
        ("corePoolSize: " + corePoolSize)

Of course, this involves dividing up the checks and throwing custom exceptions for each illegal input. Preferrably, the exception should list all illegal inputs detected. Actual error handling logic now: More work for the programmer!

More work it is. A hell of a lot of work, actually, like all things code-related. But I think this is an important complement to open source – the open runtime! The closed runtime simply throws an exception (at best). Working with closed runtimes are just as inconvenient as closed source, and given the choice, I’m not so sure I would choose the open source every time.

The open runtime, on the other hand, consciously goes about telling you what’s wrong, instead of hiding it – it considers the task of assembling and emitting error information an important part of its logic.

Maintaining an open runtime is the responsibility of all code loaded into the VM; the application, the libraries, the framework(s). And yes, the standard library as well. The Java object system provides one vital component: exceptions with messages. Equally important is the facility of exception chaining, which I won’t go into here – just do it. However, the third component is often overlooked: The Object toString() method.

Implementing a sensible toString is about the best thing you can do for prosperity, world peace a close second. It means everyone can benefit from using your object in exception messages, as well as log messages. It means every log message and exception they appear in will become a little more informative. If you provide a library used by many, the benefits are boundless. You know a good toString method when you see its output: It tends to describe important state (for value objects) and/or identity (for entities). Important state here being e.g. the factors that determine how the instance will behave, or what its logical meaning is. (If any.)

So everyone has the responsibility of opening up the runtime, and the further “down” you tend to be, the bigger your responsibility. It’s a trickle-up effect! What would the world be like if an int presented itself as e.g. java.lang.Integer@123123? A lot more difficult to debug, for one thing. Such transparency makes more or less sense for all objects, especially if they are in heavy rotation. So, if they end up in a log message or an exception message, they contribute by adding meaning to it – every time. Adding a toString is a lot better for your karma than not, which is basically like being a time-sucking vampire. A closed runtime sucks time and energy from all who touch it, from fellow developers to IT staff who have to keep it running.

The Java standard library should definitely know its role in making Java runtimes more open. But e.g. ThreadPoolExecutor doesn’t implement toString – how many man-years have been lost to debugging because of that? (It’s not that I want to know, I was going for rhetorical.)

To sum up: Just implement toString sensibly, assemble enlightening exception messages, and always wrap the cause. Afterwards, the world is a little better, your runtime (and possibly others) will be more transparent and less closed, and everyone has more time to write code, because they don’t have to dig around in a debugger to find out what the hell is making your code scream. And, bonus, you won’t see your code in my blog, I promise.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: