February 23, 2009

GWT and deferred binding

I was going through last year's Google I/O conference videos and noticed a few GWT-related ones. One in particular seemed interesting: Faster-than-Possible Code: Deferred Binding with GWT by Bruce Johnson.

The technique that GWT dubs "deferred binding" consists of generating feature-specific output code (JavaScript) from a common codebase (Java for GWT, Lisp for Parenscript) and serving it up under different URLs so the resource are cached properly.

I first encountered the idea in the spring of 2007 when Daniel Gackle proposed it as a way of efficiently handling the generation of feature-specific JavaScript code from Parenscript, and we implemented it in a few days.

The system would generate several pages from a common definition written in CL-WHO/Parenscript (we used it to generate browser-specific code and profiler-instrumented code, so in all we'd get a cartesian product of (ie, ff) x (regular, profiled) as output), and serve them up under different URLs that also incorporated a version number (via a mechanism that linked source files to generated resources and tracked the file modification date). This approach generated perfectly cacheable HTTP resources and ensured trouble-free application upgrades.

Something interesting that I noticed when developing the feature-specific code generation mechanism was its resemblance to context-oriented programming: each feature acts as a layer which affects the way that the compiler produces code.

Besides browser-specific code generation, in GWT the technique is used for generating locale-specific resources, and by virtue of its implementation, to provide an extremely obtuse way to emulate Java's broken metaprogramming facilities (see http://www.zenika.com/blog/wp-content/uploads/2007/08/tutorial-binding-en.pdf, for example).

In the intervening time I have thankfully learned a little more about programming for the web, and have come to the inevitable conclusion (if I had started reading comp.lang.javascript sooner, I could have avoided making this mistake - if you're not reading that group yet, start now) that using the approach to generate browser-specific code is fundamentally flawed and will almost certainly ensure that your code will break on browsers that you have not developed for. Working to add support for new browsers to this scheme will not only waste an incredible amount of time that you would not have had to spend at all otherwise, but will actually make your code more brittle and harder to maintain.

The only viable approach to dealing with differences in browser capabilities is feature detection. I can only say that I am glad that Parenscript is not pushing a "framework" on anybody, so my ignorance only impacted one project. Generating feature-specific code is not in itself a bad idea - GWT uses it to also generate locale-specific resources, with the corresponding bandwidth savings and cacheability advantages. I can only hope for the sake of their users that the GWT developers repent and change their stance on generating browser-specific code.

No comments: