Saturday, June 30, 2007

The Blogging Professional

It is a melancholy experience for a professional mathematician to find himself writing about mathematics. The function of a mathematician is to do something, to prove new theorems, to add to mathematics, and not to talk about what he or other mathematicians have done. Statesmen despise publicists, painters despise art-critics, and physiologists, physicists, or mathematicians have usually similar feelings: there is no scorn more profound, or on the whole more justifiable, than that of the men who make for the men who explain. Exposition, criticism, appreciation, is work for second-rate minds.

-- G. H. Hardy (PDF link)

Saturday, June 23, 2007

Crockford's revisions to ECMAScript

The ECMAScript standard is undergoing growing pains right now, and for the first time since 1999, it looks like major revisions to the language may take effect soon. Douglas Crockford has recommendations of his own. While I don't have any strong feelings about the new features he requests (they can mostly be implemented in the JavaScript we already have), his Corrections are mostly sane things that will remove a lot of the suckiness from the current standard:

  1. Reserved words
  2. Standardize implementation of trailing commas in object literals and arrays
  3. Make arguments object a true array
  4. Tail recursion optimization
  5. Deprecate primitive type wrappers, the with statement, semicolon insertion, arguments.callee, typeof, and eval.

It looks like Brendan Eich is well aware of Crockford's longstanding laments, particularly against the with statement and the reserved words restrictions, and has addressed them in the draft spec for ECMA-262 v4.

Crockford objects to restricting the use of reserved keywords in object definitions as unnecessary. According to his argument, usage such as:

var o = {
    class: 'style', 
    with: function (n) { return n+'a top hat'; }
};

will preserve the original use of these names, as the names are merely being used for scoped member properties; they cannot be confused in this context, syntactically, with the "official" uses of these keywords. (This is, apparently, why the JSON spec requires double-quoted property names.) However, it seems this restriction is in place mainly to make possible the use of the with keyword; consider:

with (o) {
   class = 'none';
   with(class);
}

If using these keywords were legal above, their use with the with statement here invites syntax hell.

I for one would be happy to see the demise of the with keyword. It breaks with JavaScript's function-level scoping, and creates more problems than it's meant to solve. It "feels" uncharacteristic of the language, since it promotes an object's properties from "property" status into "variable" status, blending them indiscriminately into the surrounding scope. JavaScript has enough trouble affording decent namespacing as it is; this "feature" smacks of bad practice.

More than adding new features, we could use a "trimming-down" phase to the language. While Mozilla toils at turning JavaScript into Python and other power-players at ECMA (presumably MS?) seek to remake the spec in the image of Java or C#, I'm mostly happy with the way it is - just please, for God's sake, fix the problems that are currently there before bounding into a new round of ill-conceived feature bloat.

We front-end developers are lucky to be enjoying a golden age of JavaScript. But the clouds of confusion and incompatibility are on the horizon. I don't see a compelling reason to add Java-style classical inheritance to the language, and I see even less a possibility of the vendors agreeing to ship timely implementations of this new spec.

Surely wiser heads than mine are laboring on this problem. But I guess I'm just not seeing that JavaScript falls short in ways that warrant changing it beyond recognition.

Tuesday, June 5, 2007

Code Modularization and CSS Queries

On his personal blog, YAHOO! front-end engineer Nicholas Zakas takes on the prevalence of the CSS query engine in client-side JavaScript libraries. The flexibility of some other quick syntax shorthand for accessing HTML elements and describing structure without using the conventional DOM methods has always appealed to me, so I wasn't sure what he was missing.

Granted, the recent proliferation of JS libraries in general (and query engines in particular) has been rather excessive, no doubt tracking a boom and bust path. I'm a fan of all of these efforts, though I wouldn't use most of them myself - they represent attempts to impose order onto the chaotic soup of client-side code that we've been dealing with since 1996. Each one - Prototype's dubious extensions to native objects, jQuery's wrapping of DOM elements and telltale method chaining, Mochikit's Python-like syntax - represents a new experiment in turning the best approximation we've ever had to a cross-OS, open-source application platform - the web browser - into the full-fledged application framework it's destined to be. Even if not all of these attempts have been useful, they've at least been instructive.

After reading his replies to comments to his post, and after an informal conversation with Joel Webber at the recent Google Developer Day, I realized that client-side techniques vary widely across organizations.

At Zillow, for example, we go to great lengths to separate our HTML, CSS, and JavaScript. Since our site is fairly complex and design-heavy, and code iterations happen with such frequency, this modularization is key to keeping sane. So we have a set of rules we follow:

  1. All pieces of client-side code have a well-defined means for interacting with each other. For CSS -> HTML, it's CSS selectors. For JS -> HTML, it's the DOM. For JS -> CSS, it's classnames. For HTML -> JS, it's the DOM events model.
  2. Do not mix HTML, CSS, and JavaScript. No inline styles, no inline event handlers, no creating elements via JavaScript.

You see where I'm going with this - HTML, CSS, and JavaScript are to exist independently of one another and "flip switches" rather than assemble by hand. For the same reason you wouldn't write code like

function makeBoldRed(el) {
    el.style.fontWeight = 'bold';
    el.style.color = 'red';
}

but rather

Element.addClass(el, CSS.ERROR_MESSAGE);

I prefer to use CSS-style selectors to fix the gap, and allow JavaScript to refer to HTML using the same syntax that its presentation counterpart does.

However, it appears that some large companies are generating HTML through JavaScript. This can work too, but in this case your goals are going to be much different. Once you start working this way, you risk accessibility and graceful degradation. You also lose the ability to develop and test presentation-layer components independently of one another, and this can lead to a poorer design or, at the very least, longer development and testing time. Another problem is debugging; if you start permitting your script to tinker with your HTML, or if your script depends on a fixed HTML structure to function properly, design changes can lead to interminable headaches when a complex script's dynamic change to the DOM structure goes undetected.

Sure, CSS queries can be performance bottlenecks. But usually they aren't, at least not when you're using a throughly-tested engine such as are available in the major JS libraries. A minor performance hit - most query engines can perform the most complex queries in under 5 ms, depending on your machine - is a small price to pay for the flexibility of modular code.

On a side note, I was most intrigued by Joel Webber's description of the Google Web Toolkit's function: to add a compile-time step to optimize and inline JavaScript code. I can appreciate that. Certainly, a well-written compiler will be able to optimize code to a greater degree than a meticulous programmer. But why Java? Why apply this essentially alien style of programming to the client? This question remains outstanding for me.