Archive for the 'Technology' Category

Infallible APIs

Fellow Atlassian Charles Miller recently wrote an amusing post about methods and constructors in Java that declare a checked exception, but can be called in a way that is required by the specification not to fail. A common example involves string encodings:

try {
    s = new String(byteArray, "UTF-8");
} catch (UnsupportedEncodingException e) {
    throw new Error("UTF-8 is missing??");
}

This code is the result of two conflicting factors. On one hand, since the constructor in question takes an arbitrary character encoding, the case of the encoding being unavailable must be taken into account. On the other hand, 90% of code that calls this constructor will be explicitly invoking a character set that is required to be provided with the Java Runtime Environment, and its absence would be an error serious enough to justify terminating the VM entirely.

The unnecessary exception-handling code is ugly, and obscures the actual intent of the method in which it appears. Charles jokingly proposes adding a “yoda” statement to Java to tell the JVM, “do, or do not; there is no try.”

Another Solution

Usually, code smells like this indicate a poorly-designed API. If you know the method can be called in a way such that failure would mean there’s an internal error, then it shouldn’t be throwing a checked exception. As is often the case, you could solve this problem with stronger types:

public class Charset {
    public static Charset findByName(String charsetName)
        throws UnsupportedEncodingException
    // ...
    public static class Standard {
        public static final Charset UTF_8 = //...
        public static final Charset US_ASCII = //...
        /// etc.
    }
}

Then give String a new constructor:

    public String(byte[] bytes, Charset charset) {
        // no exception declared!
        //...
    }

Now you’ve got a few different ways to use this. When you know you want to use a built-in encoding:

    String s = new String(byteArray, Charset.Standard.UTF_8);
    // no checked exception here!

When you want to use a variable encoding, that may or may not be defined in this VM:

    Charset charset;
    try {
        charset = Charset.findByName(charsetName);
    } catch (UnsupportedEncodingException e) {
        System.err.println("Unknown charset: " + charsetName
            + "; falling back to US-ASCII");
        charset = Charset.Standard.US_ASCII;
    }
    String s = new String(byteArray, charset);

And the original String constructor could remain—rewritten to use the new Charset facilities—as a convenience for the case where you really do want to use an unknown encoding, and fail if it’s not present:

    try {
        String s = new String(byteArray, charsetName);
    } catch (UnsupportedEncodingException e) {
        System.err.println("Unknown charset: " + charsetName
            + "; ignoring");
    }

The Worst Part of it All

As it happens, Sun, did add a Charset class to Java in 1.4, as part of the NIO framework. Astonishingly, they still did not define constant implementations of Charset for the set of required standard ones. So you still have to look them up by name, and you still have to catch an exception! Worse yet, they invented some new exceptions for the purpose, UnsupportedCharsetException and IllegalCharsetNameException. These exceptions are unchecked runtime exceptions, which avoids the problem of having to clutter your code with exception handling code in the cases where you are using a standard charset, but makes it easier to mishandle cases where you aren’t.

The kicker, though, is that String does not have a constructor that accepts a Charset object! Instead, you’re supposed to use the CharsetDecoder class or the decode method of Charset, which wraps everything in Buffer objects, making you jump through a few hoops to accomplish the same things:

    String s = Charset.forName(charsetName).decode(ByteBuffer.wrap(byteArray)).toString();
    // this might throw an exception, but it's unchecked
    // so we don't need to catch it unless we want to handle it

Ick.

Still, though, the NIO charset handling is a little bit better than what we had before, and it gives you some flexibility that wasn’t there in the previous implementation (for example, you can control how to handle unmappable byte sequences). It wouldn’t be too hard to add in a few utility methods to smooth over the rough edges here. I’ll leave that as an exercise for the reader.

Macworld 2008 Predictions

This year, even more than ever before it seems, everyone has a pet theory on what Steve Jobs will be announcing at tomorrow’s Macworld Expo keynote session. Since I’ve got my own ideas and have been trying to get myself to write on this site more often, I’ll throw in my two cents on the matter. I don’t have much that hasn’t already been said by many others, so I’ll try to keep this interesting.

My money is on wireless as the keynote’s theme. Obviously I’m not the first to say this, and the banners in the Moscone Center are a big clue, but you’ll just have to take my word that I’ve suspected this for a while now. It’s clear to me that Jobs and Apple’s industrial design team must not be big fans of lots of cables hanging off a computer (and who is?) so it wouldn’t surprise me at all if there are teams of engineers trying to build a perfectly cable-free computer at Apple. I don’t know if they’ve gone quite that far yet, but I bet that the sub-notebook that they’re almost certainly announcing tomorrow will be pretty close.

I’m typing this right now on a rev A 12″ PowerBook G4 that I bought in May of 2003. It’s reaching the end of its life — it won’t actually run on batteries anymore, so I need to keep it tethered to a wall — but five years ago, this was an incredible machine. It was compact, lightweight, fast, full-featured, and beautifully designed; it was one of the best computers Apple had ever created, and still is.

There’s absolutely no way that the notebook computer Apple is announcing tomorrow will be anything like the 12″ G4. That is, they’re not putting a MacBook in a smaller package. If they were planning to do that, it would have already happened. The MacBook Pro is a fairly incremental update to the same basic design that started with the Aluminum PowerBooks, and a smaller version of those would not be noteworthy enough to headline the keynote presentation.

Instead, I think we’ll see a radically new computer that not only looks like nothing we’ve seen before, but presents us with an entirely new way of using and even thinking about portable computers.

Many of the rumor sites have reported that the new design will not include a built-in optical drive. The assumption is that it will be available as an external unit, but I’m not so sure. I find it just as likely, or even more likely, that Apple will instead announce a shift to fully electronic software distribution, perhaps even selling third-party software, probably leveraging the iTunes Store. This rumored MacBook Air will receive all of its updates wirelessly.

I would not be surprised if there are no peripheral ports at all on the device. External devices will use Bluetooth. Backups will use wi-fi with an Airport Extreme AirDisk, a feature present in the Leopard development versions of Time Machine that slipped from the final release, but will very likely return tomorrow, maybe even with a new, Apple-branded hard drive or RAID array with integrated wireless. I am more hesitant to believe the rumors that they will announce ubiquitous wireless networking using WiMax, EDGE or EVDO, but it’s not out of the question and it would surely be welcome.

In the cases where you do need removable storage, the solution is literally right in front of most of us. I don’t think it was happenstance that many of the new features of Leopard were oriented around easier network setup, more flexible sharing, and remote access. I’ve got a feeling that the MacBook Air will be a computer that is explicitly designed as a companion device — one that is not intended to stand alone as your primary work machine, but to provide a portable window into the desktop machine that you most likely have sitting on your desk already at home or at work.

The pieces fit together perfectly: with Leopard’s Back to My Mac, Apple has already solved the problem of sharing files across the Internet, meaning that a portable device only needs to be powerful enough to get onto the network, connect to a host computer, and sync over whatever data you need here and now, or maybe even just act as a dumb terminal using screen sharing to control the desktop Mac directly. The limited need for speed, memory, storage and expansion ports then frees the hardware engineers to optimize for battery life, wireless performance, and weight. It could all add up to something pretty revolutionary: a truly ultra-portable computer that would not need to be much larger than a magazine but could potentially provide the power of a Mac Pro wherever you are.

Now, it’s pretty likely that a lot of my “prediction” is really more like projection. The fact is, this is exactly the kind of computer that I’d really like right now. I’ve got Mac desktops at home and at work, and I’m completely happy with them except on the occasions where I go out of town… or just feel like blogging from a cafe or browsing Google Reader on the couch. It’s hard to justify buying a full-featured laptop for those occasions, not just because of the price, but because of the hassle of keeping my data in sync, not to mention lugging it around in my bag. If the MacBook Air turns out to be anything like I hope, Apple will surely get more of my money tomorrow.