2009-02-25

Swing 2: Pissing in the Wind

As nerds, it's all too easy for us to focus on technical merits to the exclusion of all else. Sadly, here in the real world, technical merits aren't the be-all and end-all. Repugnant though it may sound to some ears, most things come down to economics.

Take Swing 2, for example. The "vision" is the somewhat ungrammatical "Leverage current Swing know-how to create modern version Swing". But that's not what they mean. What they mean is "use Java 5 language features to perturb the Swing API". Specifically, the current focus is on cleaning up Swing's admittedly old-fashioned API: using enumerations instead of integer constants, using generics, and adding "varargs support". (I'm not sure quite what's meant by the last one, but it doesn't matter for the purposes of this post.)

Sun – sensibly enough – is not interested in making these changes, so the "Swing 2" guys plan to fork.

Why wouldn't Sun be interested? Surely it's embarrassing that JList has a constructor that takes a Vector<?>, for example? Surely there's no doubt that an enum is a better way to specify an enumeration than a bunch of ints? Surely we should splash some varargs around, now we have them?

Danny Coward responded but appears to have been too polite to get the point across.

That's where I come in.

If you read Danny Coward's response, check out the bits in bold. That's what a sane man sounds like. He talks about making it "easier to develop with Swing" and making the "runtime deploy and perform better". As long as "perform" covers look and feel as well as space/time performance, I don't think anyone could disagree that those are the most important possible goals for Swing.

The other important goal would probably be "enable developers to build stuff they can't currently build", but that seems to be the one Sun always ignores. They're too busy catching up with functionality that was old hat even in the days of Windows 95. (An about box, say, or a font dialog, or an embeddable browser component, or any number of other fairly basic things we still don't have in Java in 2009.)

I've written and worked on numerous Swing applications now, and can honestly say that none of the ideas mentioned so far for the third-party "Swing 2" would have helped in any way...

Enums What would making BorderLayout.EAST and friends enum constants buy me? I'll grant you that the Font constructor can be troublesome (which is it; size then flags, or flags then size?) but Font.deriveFont is a perfectly adequate work-around for that. Plus Font doesn't count because it's part of AWT, not Swing.

Generics Translating to or from a legacy collection is the work of a single line. More importantly, using a collection directly as your model is hardly defensible as good practice, so this just isn't an issue that comes up. (If you really want to improve the Swing model situation, you probably want to be thinking more along the lines of something like Glazed Lists.)

Varargs I'm baffled there. Varargs methods are occasionally useful, but Arrays.asList and/or Collection.toArray ensure that their absence is never a major problem. And see Bloch's Effective Java 2e (item 42) for warnings about over-using varargs.

Nothing in the current "Swing 2" plan has any real value to the developer of Swing applications, or to the developer's users.

It doesn't make existing stuff any easier to write.

It doesn't make existing stuff work any better.

It doesn't make it possible to write stuff you couldn't write before.

And what does "Swing 2" cost me, a Swing developer who's thinking of using "Swing 2" despite the fact that it doesn't do anything useful? Well, it costs me an extra dependency. A dependency on a fork of something that's under continued development. A dependency that won't auto-update itself with future Java releases; you'll have to re-release your application too. Oh, and I have to rewrite my source to be incompatible with what everyone else is using.

And that's as complex as your economic insight needs to be in this case. You look at what you're getting, and you look at what it's costing you, and you decide whether it's worth the bother.

The Nimbus LAF is an interesting contrast. It's equally worthless (if I wanted a LAF that looks like ass and shouts "crappy Java app", I'd use Metal), but Nimbus doesn't cost me anything except the engineering time that was wasted on it, and I had no influence over that anyway. So who cares?

You could accuse me of Python 3K blindness here. When that came out, existing Python users complained that it changed stuff unnecessarily, and even broke the "hello world" that's in all the tutorials. Am I not making the same complaint about "Swing 2"? No. What the Python old-timers were missing, I think (as someone who doesn't like Python, but thinks Python 3K is at least a little less bad than Python 2), is that while in the short term all the tutorials are broken, they'll soon be fixed, and everyone will be better off with a slightly less grody language. Python 3K aims to make things better for the future – where it'll be called just "Python" – at some cost to the past.

"Swing 2" doesn't improve the future, though, because it's a fork that will wither and die for lack of purpose. No tutorials will be rewritten, because they'll always have to refer to the One True Swing anyway. Anyone foolhardy enough to change their code to rely on "Swing 2" will end up changing their code back again, but don't worry: there will be precious few such people, and they won't be people writing actual applications anyway — those people will be worrying about stuff that actually makes a difference rather than unfortunate trivia.

If you want to do something that will make a difference, there are tons of things that are a real pain in Swing at the moment. JFileChooser, JOptionPane, JTable, and SwingWorker are all obvious examples of classes it's pretty hard to write a serious Swing application without, and yet all of which need to be taken outside and shot. And don't forget the ugly stepsisters JTextArea and JTextPane. You could write a decent replacement for any or all of those. Or you could look at some of the deeper stuff like the roles of ActionMap and InputMap and whether menus should really deal in Actions, and how the "Edit" menu works in Cocoa compared to how it never really works right in Swing. Or you could work on giving us abilities we don't currently have; an embeddable web browser with a sensible interface, that's available on all platforms, and that doesn't crash, say. Or you could try to address some of the difficulties of writing cross-platform Swing applications.

If you honestly think that using enums, generics, and varargs in the existing code are anything more than pissing in the wind, you need to read and write more Swing applications.

Or maybe try living without your little toolkit you've been using as a crutch that's prevented you from seeing the real problems. I personally never fight JOptionPane any more, for example, because I've written my own wrapper that beats some sense into it. But that doesn't mean JOptionPane is anything above awful. (This is the Python 3K blindness: it's harder for old-timers to appreciate how broken things are because they've got a good feel for where the dangerous swamps are, and ready-made duckboards for the areas they can't avoid. And aren't you supposed to get a bit wet anyway?)

The only advantage I can see of attacking the non-problems of enums, generics, and varargs is that they're easy problems. Imagine, by comparison, the amount of work involved in writing and maintaining your own JTextArea replacement (like the jessies.org one). And that's a tiny project compared to any reasonable "Swing 2". If you don't have the stomach for one of these wafer-thin mints, you can forget about anything as grandiose as "Swing 2".

Don't get me wrong: you can "fix" these trivial API warts, but you need to provide something worthwhile to go with those changes. If people were already using "Swing 2" because, say, it had a JTable replacement based on Glazed Lists, they might then swallow the trivia. But try to do things the other way round, and your project is stillborn.

Although, given that the currently perceived "enemy" of Swing is JavaFX, you might even want to revisit the very premise of Swing and ask whether we shouldn't really be talking about "AWT 2" instead of "Swing 2". In a sense, JavaFX is Sun making the Swing mistake all over again. (The main difference is probably that last time they were too early to the party; this time they're too late. And at least this time I haven't heard them say it'll be okay for the desktop too.)