The Source for Java Technology Collaboration
User: Password:
Register | Login help    

Search

Online Books:
java.net on MarkMail:


Evolution vs Intelligent Re-design?

Posted by javakiddy on February 13, 2008 at 4:12 PM PST

You know you're getting old when you find yourself complaining about how English is being butchered, instead of inventing new ways to butcher it yourself.

Languages change and evolve, they cannot stand still. This applies to programming languages just as much as natural written/spoken language. The difference is, of course, natural languages don't require backwards compatibility. It's this which causes the headaches — if we could just add keywords whenever we wanted, or retrofit the grammar at the drop of a hat, there wouldn't be a problem. But there's a huge body of Java code already out there, and it would be nice if none of it got broken by any changes.

I wonder if this is why programming languages, unlike natural languages, seem to have shelf lives? In nature the success of a species is constrained by the size of its compatible habitat. As the environment changes a species may evolve, but only up to a point. Eventually its popularity fades and better adapted animals arrive to dominate the landscape.

In programming, a dramatic environmental shift began at the end of the Seventies when the personal computer saw the end of dinosaur Mainframes, and with them stalwart languages like COBOL in favour of C and later C++. Fifteen years on and the internet saw C and C++ slowly retreat into niche markets, replaced by net-savy new blood in the form of Java, JavaScript, PHP, etc.

Why couldn't COBOL just evolve to become less 'records and batch processing', and more 'files and interactivity'? Why couldn't C just evolve to be less 'bytes and memory pointers', and more 'bytecode'? The answer is they could have — but there's only so much retro-fitting one can do to an established technology...

So how far can Java continue to evolve before it too goes the way of the dinosaur?

Seeking closure (groan!)

[I'm taking my life in my hands with the below — language design isn't really my field. So treat this blog as a 'view from the trenches', rather than the considered opinion of someone who's spent decades developing compilers.]

An issue came up on the comments for Kirill Grouchnikov's blog "Evolving the language" (a reply to his own "And so it begins...") relating to the use of the BGGA Closures for event handling. While the BGGA proposal is slightly more than just a lightweight replacement for anonymous inner classes, when it comes to event handling it's the removal of the inner class boilerplate which seems the biggest selling point.

As samyron pointed out in the comments of the Kirill's blog, the following code...

button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
processAction(e);
}
});

...would be translated into...

button.addActionListener({ActionEvent e => processAction(e)});

...which, at first glance, certainly seems more compact.

Although the closure syntax may be a little more cryptic to the untrained eye, this it outweighed by the reduced need for boilerplate. If your code is merely a short and snappy negative/positive/zero condition to sort a collection, or a filename filter for JPEGs, it's likely to be dwarfed by the enclosing anonymous inner class code. So a leaner syntax on the face of it certainly does seem useful.

But event handlers typically have to load/save data, interact with objects, update the UI state, talk to databases, etc. — all this means they are rarely single statement affairs. A more realistic event handler might be (adapting the above example)...

// Sans Closures
button.addActionListener(new ActionListener()
{ public void actionPerformed(ActionEvent ev)
{ doSomething();
doAnotherThing();
doYetMoreThings();
doEvenMoreThings(withThisThing);
if(firstDayOfSpring)
{ dontForgetToDoThis();
ohAndAlmostForgotThisToo();
}
}
});

...which would translate as...

// Avec Closures
button.addActionListener({ActionEvent e => processAction(e)});
private void processAction(ActionEvent e)
{ doSomething();
doAnotherThing();
doYetMoreThings();
doEvenMoreThings(withThisThing);
if(firstDayOfSpring)
{ dontForgetToDoThis();
ohAndAlmostForgotThisToo();
}
}

It basically comes down to this: when the code body size is short, a heavyweight wrapper (as provided by anonymous inner classes) seems unreasonable. But as body expands beyond one line, the concept of a lightweight wrapper becomes more and more of an irrelevance. Indeed its impact becomes so trivial as to, some might argue, no longer justify its more cryptic syntax. The very fact that the original example hid the stodge behind a processAction() method betrays the ineffectiveness of the BGGA closure syntax for anything other than ultra-trivial blocks of code.

While I recognise Closures have several strings to their bow, I personally wouldn't count 'event handling' as one of them. In a practical sense I doubt their tight syntax would have much of an impact given the size of most event handlers. It's a bit like when your girlfriend takes her socks off in a vain attempt to cheat the bathroom scales.

The meaning of liff [*]

Of course everyone has their own favourite Java language enhancement. I, as a Swing coder, would like to see an end to the cumbersome boilerplate code for pushing stuff onto the Event Dispatch Thread. Perhaps a syntax for bundling arbitrary blocks of code into Runnables and posting them onto the end of queues?

// Ugly
SwingUtilities.invokeLater(new Runnable()
{ public void run()
{ // Your Swing code here
}
});
// Nice!  'SwingUtilities' implements an event queue interface.  (But how 
// to support invokeAndWait() ..?)
goto(SwingUtilities)
{ // Your Swing code here
}

Not that anything like the above is likely to make it into the language. :)

While the elite coder welcomes more syntactic shortcuts, the novice merely sees a steeper learning curve. A clean syntax with familiar grammatical patterns employed over and over is easier to learn than one full of cryptic looking quirks and counter-intuitive side effects.

The rather awkward way in which Generics were slotted into the existing language is already a big turn off for beginners. New programmers will always favour a syntax with a low barrier to entry for novices, rather than go faster stripes for experts. They'll vote with their feet if a language takes a dramatic turn for the worse.

The trick is to balance the two concerns — move the language forward, but not in such a way as to dramatically shorten its life expectancy. Unfortunately this can sometimes mean missing out on juicy additions, simply because the fallout would be too extreme.

But do we really need every juicy addition? Languages are tools, and each has its own strengths and weaknesses. They say French is good for making love, German for giving orders, and English for apologising — unfortunately mix-and-matching spoken language to suit your mood isn't normally an option. But computer languages are not so tightly bound: we can if so desired pick Python to write one project, Java for the next, and Ruby for a third. We can even mix them within a single project.

The Da Vinci Machine promises to re-invent Java's runtime core to suit a much wider range of languages. If this project bears fruit (and I sincerely hope it does) we may not have to worry so much about including so many new feature into the Java language itself. But this will mean that while the Java runtime will go on, the Java language itself will eventually die out.

Do we want Java to die out? An alternative is to seize the initiative and begin developing a Java replacement, a Mk. II if you like. Going back to the drawing board, we can fix all the problems with Generics and easily slot in Closures and Properties in a way which makes sense.

So how much life is their left in the current Java? We have a lot of time and effort invested in it, which has resulted in a healthy reputation, but can it last much longer? When is it time to stop evolving, and start over with an 'intelligent re-design'?

Related Topics >> Programming      
Comments
Comments are listed in date ascending order (oldest first)

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n

RED EYE OWNZ - by Z4i0n