Async Programming Part 3: Finally

As we saw in Part 1, error handling in callback-based asynchronous code gets messy quickly, and loses many of the qualities of synchronous code that make it familiar and easier to reason about. In Part 2, we introduced Promises and saw how they restore call-and-return semantics, allow errors to propagate up the stack similarly to synchronous exceptions, and generally provide a cleaner approach to managing asynchrony, especially when handling errors.

Try/catch/finally

In synchronous code, try/catch/finally provides a simple and familiar, yet very powerful idiom for performing a task, handling errors, and then always ensuring we can clean up afterward.

Here’s a simple try/catch/finally example in the same vein as the original getTheResult() from Part 1:

1
2
3
4
5
6
7
8
9
10
11
12
// Sync
function getTheResult() {

    try {
        return thisMightFail();
    } catch(e) {
        return recoverFromFailure(e);
    } finally {
        alwaysCleanup();
    }

}

As we’ve seen, attempting to simulate even the try/catch via a callback-based approach is fraught with pitfalls. Adding the notion of finally, that is, guaranteed cleanup, only makes things worse.

Using Promises, we can build an approach that is analogous to this familiar try/catch/finally idiom, without deep callback structures.

Try/catch

Let’s start with a simpler version of example above that only uses try/catch, and see how we can use Promises to handle errors in the same way.

1
2
3
4
5
6
7
8
9
10
// Sync
function getTheResult() {

    try {
        return thisMightFail();
    } catch(e) {
        return recoverFromFailure(e);
    }

}

And now, as in Part 2, let’s assume that thisMightFail() is asynchronous and returns a Promise. We can use then() to simulate catch:

1
2
3
4
5
6
7
8
9
10
11
12
// Async
function thisMightFail() {
    //...
    return promise;
}

function getTheResult() {

    return thisMightFail()
        .then(null, recoverFromFailure);

}

Waitaminit, that’s even less code than using try/catch! What’s going on here?

Propagating a success

This example introduces two very important facts about how Promises behave. The first of which is:

If no onFulfilled handler is provided to then(), the fulfillment value will propagate through unchanged to the returned Promise.

We’re not supplying an onFulfilled handler when calling then(). This means that a successful result from thisMightFail() simply will propagate through and be returned to the caller.

Handling an error

The other important behavior is:

A handler may produce either a successful result by returning a value, or an error by throwing or returning a rejected promise.

We are supplying an onRejected handler: recoverFromFailure. That means that any error produced by thisMightFail will be provided to recoverFromFailure. Just like the catch statement in the synchronous example, recoverFromFailure can handle the error and return a successful result, or it can produce an error by throwing or by returning a rejected Promise.

Now we have a fully asynchronous construct that behaves like its synchronous analog, and is just as easy to write.

Adding some sugar

Hmmm, but what about that null we’re passing as the first param? Why should we have to type null everywhere we want to use this asynchronous try/catch-like construct? Can’t we do better?

While the primary interface to a Promises/A+ Promise is its then() method, many implementations add convenience methods, built, with very little code, upon then(). For example, when.js Promises provide an otherwise() method that allows us to write this example more intuitive and compactly:

1
2
3
4
5
6
7
// Async: Using when.js promise.otherwise();
function getTheResult() {

    return thisMightFail()
        .otherwise(recoverFromFailure);

}

Now we have something that reads nicely!

Adding finally

Let’s add finally back into the mix, and see how we can use Promises to achieve the same result for asynchronous operations.

1
2
3
4
5
6
7
8
9
10
11
12
// Sync
function getTheResult() {

    try {
        return thisMightFail();
    } catch(e) {
        return recoverFromFailure(e);
    } finally {
        alwaysCleanup();
    }

}

First, let’s note that there are some very interesting things about this seemingly simple finally block. It:

  1. will always execute after thisMightFail and/or recoverFromFailure
  2. does not have access to the value returned by thisMightFail, or to the thrown exception (e), or to the value returned by recoverFromFailure 1.
  3. cannot, in this case, transform an exception thrown by recoverFromFailure back into a successful result2.
  4. can change a successful result (returned by either thisMightFail or recoverFromFailure) into a failure if alwaysCleanup throws an exception.
  5. can substitute a new exception in place of one thrown by recoverFromFailure. That is, if both recoverFromFailure and alwaysCleanup throw exceptions, the one thrown by alwaysCleanup will propagate to the caller, and the one thrown by recoverFromFailure will not.

This seems fairly sophisticated. Let’s return to our asynchronous getTheResult and look at how we can achieve these same properties using Promises.

Always execute

First, let’s use then() to ensure that alwaysCleanup will execute in all cases (for succinctness, we’ll keep when.js’s otherwise):

1
2
3
4
5
6
7
// Async
function getTheResult() {

    return thisMightFail()
        .otherwise(recoverFromFailure);
        .then(alwaysCleanup, alwaysCleanup);
}

That seems simple enough! Now, alwaysCleanup will be executed in all cases:

  1. if thisMightFail succeeds,
  2. if thisMightFail fails and recoverFromFailure succeeds, or
  3. if thisMightFail and recoverFromFailure both fail.

But wait, while we’ve ensured that alwaysCleanup will always execute, we’ve violated two of the other properties: alwaysCleanup will receive the successful result or the error, so has access to either/both, and it can transform an error into a successful result by returning successfully.

Don’t access result/error

We can introduce a wrapper to prevent passing the result or error to alwaysCleanup:

1
2
3
4
5
6
7
8
9
10
11
12
// Async
function alwaysCleanupWrapper(resultOrError) {
    // don't pass resultOrError through
    return alwaysCleanup();
}

function getTheResult() {

    return thisMightFail()
        .otherwise(recoverFromFailure);
        .then(alwaysCleanupWrapper, alwaysCleanupWrapper);
}

Now we’ve achieved one of the two properties we had lost: alwaysCleanup no longer has access to the result or error. Unfortunately, we had to add some code that feels unnecessary. Let’s keep exploring, though, to see if we can achieve the remaining property.

Don’t change the result

While alwaysCleanupWrapper prevents alwaysCleanup from accessing the result or error, it still allows alwaysCleanup to turn an error condition into a successful result. For example, if recoverFromFailure produces an error, it will be passed to alwaysCleanupWrapper, which will then call alwaysCleanup. If alwaysCleanup returns successfully, the result will be propagated to the caller, thus squelching the previous error.

That doesn’t align with how our synchronous finally clause behaves, so let’s refactor:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Async
function alwaysCleanupOnSuccess(result) {
    // don't pass result through, *and ignore* the return value
    // of alwaysCleanup.  Instead, return original result to propagate it.
    alwaysCleanup();
    return result;
}

function alwaysCleanupOnFailure(error) {
    // don't pass result through, *and ignore* the result
    // of alwaysCleanup.  Instead, rethrow error to propagate the failure.
    alwaysCleanup();
    throw error;
}

function getTheResult() {

    return thisMightFail()
        .otherwise(recoverFromFailure);
        .then(alwaysCleanupOnSuccess, alwaysCleanupOnFailure);

}

In both the success and failure cases, we’ve preserved the outcome: alwaysCleanupOnSuccess will execute alwaysCleanup but not allow it to change the ultimate result, and alwaysCleanupOnFailure will also execute alwaysCleanup and always rethrow the original error, thus propagating it even if alwaysCleanup returns successfully.

The remaining two properties

Looking at the refactor above, we can also see that the remaining two properties hold:

In alwaysCleanupOnSuccess, if alwaysCleanup throws, the return result will never be reached, and this new error will be propagated to the caller, thus turning a successful result into a failure.

In alwaysCleanupOnFailure, if alwaysCleanup throws, the throw error will never be reached, and the error thrown by alwaysCleanup will be propagated to the caller, thus substituting a new error.

Finally?

With this latest refactor, we’ve created an asynchronous construct that behaves like its familiar, synchronous try/catch/finally analog.

More sugar

Some Promise implementations provide an abstraction for the finally-like behavior we want. For example, when.js Promises provide an ensure() method that has all of the properties we achieved above, but also allows us to be more succinct:

1
2
3
4
5
6
7
8
// Async: Using when.js promise.ensure();
function getTheResult() {

    return thisMightFail()
        .otherwise(recoverFromFailure)
        .ensure(alwaysCleanup);

}

Finally

We started with the goal of finding a way to model the useful and familiar synchronous try/catch/finally behavior for asynchronous operations. Here’s the simple, synchronous code we started with:

1
2
3
4
5
6
7
8
9
10
11
12
// Sync
function getTheResult() {

    try {
        return thisMightFail();
    } catch(e) {
        return recoverFromFailure(e);
    } finally {
        alwaysCleanup();
    }

}

And here is the asynchronous analog we ended up with something that is just as compact, and easily readable:

1
2
3
4
5
6
7
8
// Async
function getTheResult() {

    return thisMightFail()
        .otherwise(recoverFromFailure)
        .ensure(alwaysCleanup);

}

Try/finally

Another common construct is try/finally. It is useful in executing cleanup code, but always allowing exceptions to propagate in the case where there is no immediate recovery path. For example:

1
2
3
4
5
6
7
8
9
10
// Sync
function getTheResult() {

    try {
        return thisMightFail();
    } finally {
        alwaysCleanup();
    }

}

Now that we’ve modeled a full try/catch/finally using Promises, modeling try/finally is trivial. Similarly to simply cutting out the catch above, we can cut out the otherwise() in our Promise version:

1
2
3
4
5
6
7
// Async
function getTheResult() {

    return thisMightFail()
        .ensure(alwaysCleanup);

}

All of the constraints we’ve been attempting to achieve still hold—this asynchronous construct will behave analogously to its synchronous try/finally counterpart.

Using it

Let’s compare how we would use the synchronous and asynchronous versions of getTheResult. Assume we have the following two pre-existing functions for showing results and errors. For simplicity, let’s also assume that showResult might fail, but that showError will not fail.

1
2
3
4
5
// Assume showResult might fail
function showResult(result) { /* Format and show the result */ }

// Assume showError will never fail
function showError(error) { /* Show the error, warn the user, etc. */ }

Synchronous

First, the synchronous version, which we might use like this:

1
2
3
4
5
6
// Sync
try {
    showResult(getTheResult());
} catch(e) {
    showError(e);
}

It’s quite simple, as we’d expect. If we get the result successfully, then we show it. If getting the result fails (by throwing an exception), we show the error.

It’s also important to note that if showResult fails, we will show an error. This is an important hallmark of synchronous exceptions. We’ve written single catch clause that will handle errors from either getTheResult or showResult. The error propagation is automatic, and required no additional effort on our part.

Asynchronous

Now, let’s look at how we’d use the asynchronous version to accomplish the same goals:

1
2
3
// Async
getTheResult().then(showResult)
    .otherwise(showError);

The functionality here is analogous, and one could argue that visually, this is even simpler than the synchronous version. We get the result, or rather in this case, a Promise for the result, and when the actual result materializes (remember, this is all asynchronous!), we show it. If getting the result fails (by rejecting resultPromise), we show the error.

Because Promises propagate errors similarly to exceptions, if showResult fails, we will also show an error. So, the automatic the behavior here is also parallel to the synchronous version: We’ve written single otherwise call that will handle errors from either getTheResult or showResult.

Another important thing to notice is that we are able to use the same showResult and showError functions as in the synchronous version. We don’t need artificial callback-specific function signatures to work with promises—just the same functions we’d write anyway.

Putting it all together

We’ve refactored our getTheResult code to use Promises to eumlate try/catch/finally, and also the calling code to use the returned Promise to handle all the same error cases we would handle in the synchronous version. Let’s look at the complete Promise-based asynchronous version of our code:

1
2
3
// Using getTheResult()
getTheResult().then(showResult)
    .otherwise(showError);
1
2
3
4
5
function getTheResult() {
    return thisMightFail()
        .otherwise(recoverFromFailure)
        .ensure(alwaysCleanup);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function thisMightFail() {
    // Using the proposed Promises/A+ style API for promise creation
    return makePromise(function(resolve, reject) {
        var result, error;

        // Do work, then:

        if(error) {
            reject(error);
        } else {
            resolve(result);
        }
    });
}

The end?

Of course, there will always be differences between synchronous and asynchronous execution, but by using Promises, we can narrow the divide. The synchronous and Promise-based versions we’ve constructed not only look very similar, they behave similarly. They have similar invariants. We can reason about them in similar ways. We can even refactor and test them in similar ways.

Providing familiar and predictable error handling patterns and composable call-and-return semantics are two powerful aspects of Promises, but they are also only the beginning. Promises are a building block on which fully asynchronous analogs of many other familiar features can be built easily: higher order functions like map and reduce/fold, parallel and sequential task execution, and much more.


  1. You might be wondering why we want this property. For this article, we’re choosing to try to model finally as closely as possible. The intention of synchronous finally is to cause side effects, such as closing a file or database connection, and not to transform the result or error by applying a function to it. Also, passing something that might be a result or might be an error to alwaysCleanup can be a source of hazards without also telling alwaysCleanup what kind of thing it is receiving. The fact that finally doesn’t have a “parameter”, like catch means that the burden is on the developer to grant access to the result or error, usually by storing it in a local variable before execution enters the finally. That approach will work for these promise-based approaches as well.

  2. Note that finally is allowed to squelch exceptions by explicitly returning a value. However, in this case, we are not returning anything explicitly. I’ve never seen a realistic and useful case for squelching an exception that way.

Async Programming Part 2: Promises

In Part 1, we looked at the awkward situation created when we introduce callbacks to handle even a single asynchronous operation into an otherwise simple set of function calls.

As a quick review, have a look back at the code we started with, the messy end result when using callbacks, and the things we’d like to fix in order to get back to sanity:

  1. We can no longer use a simple call-and-return programming model
  2. We can no longer handle errors using try/catch/finally
  3. We must add callback and errback parameters to every function signature that might eventually lead to an asynchronous operation

Promises

A Promise (aka Future, Delayed value, Deferred value) represents a value that is not yet available because the computation that will produce the value has not yet completed. A Promise is a placeholder into which the successful result or reason for failure will eventually materialize.

Promises also provide a simple API (see note below) for being notified when the result has materialized, or when a failure has occured.

Promises are not a new concept, and have been implemented in many languages. While several implementations of the Promise concept in Javascript have been around for a while, they have started to gain more popularity recently as we start to build bigger, more complex systems that require coordinating more asynchronous tasks.

(NOTE: Although there are several proposed Promise API standards, Promises/A has been implemented in several major frameworks, and appears to be becoming the defacto standard. In any case, the basic concepts are the same: 1) Promises act as a placeholder for a result or error, 2) they provide a way to be notified when the actual result has materialized, or when a failure has occurred.)

The Canonical XHR Example

In the case of an XHR Get, the value we care about is the content of the url we’re fetching. We know that XHR is an asynchonous operation, and that the value won’t be available immediately. That fits the definition of a Promise perfectly.

Imagine that we have an XHR library that immediately returns a Promise, as a placeholder for the content, instead of requiring us to pass in a callback. We could rewrite our asynchronous thisMightFail function from Part 1 to look like this:

(Note that several popular Javascript libraries, including Dojo (see also this great article on Dojo’s Deferred by @bryanforbes) and jQuery, implement XHR operations using promises)

Now, we can return the Promise placeholder as if it were the real result, and our asynchronous thisMightFail function looks very much like a plain old synchronous, call-and-return operation.

Taking Back the Stack

In a non-callback world, results and errors flow back up the call stack. This is expected and familiar. In a callback-based world, as we’ve seen, results and errors no longer follow that familiar model, and instead, callbacks must flow down, deeper into the stack.

By using Promises, we can restore the familiar call-and-return programming model, and remove the callbacks.

Restoring Call-and-return

To see how this works, let’s start with a simplified version of the synchronous getTheResult function from Part 1, without try/catch so that exceptions will always propagate up the call stack.

Now let’s introduce the asynchronous thisMightFail from above that uses our Promise-based XHR lib.

Using Promises, getTheResult() is identical in the synchronous and asynchronous cases! And in both, the successful result or the failure will propagate up the stack to the caller.

Removing Callbacks

Notice also that there are no callbacks or errbacks (or alwaysbacks!) being passed down the callstack, and they haven’t polluted any of our function signatures. By using Promises, our functions now look and act like the familiar, synchronous, call-and-return model.

Done?

We’ve used Promises to refactor our simplified getTheResult function, and fix two of the problems we identified in Part 1. We’ve:

  1. restored call-and-return
  2. removed callback/errback/alwaysback parameter propagation

But, what does this mean for callers of getTheResult? Remember that we’re returning a Promise, and eventually, either the successful result (the result of the XHR) or an error will materialize into the Promise placeholder, at which point the caller will want to take some action.

What about the Caller?

As mentioned above, Promises provide an API for being notified when either the result or failure becomes available. For example, in the proposed Promises/A spec, a Promise has a .then() method, and many promise libraries provide a when() function that achieves the same goal.

First, let’s look at what the calling code might look like when using the callback-based approach:

Now, let’s look at how the caller can use the Promise that getTheResult returns using the Promises/A .then() API.

Or, more compactly:

WAT

(Image from The Meta Picture)

Wasn’t the whole point of this Promises stuff to avoid using callbacks? And here we are using them?!?

Stay with Me

In Javascript, Promises are implemented using callbacks because there is no language-level construct for dealing with asynchrony. Callbacks are a necessary implementation detail of Promises. If Javascript provided, or possibly when it does provide in the future, other language constructs, promises could be implemented differently.

However, there are several important advantages in using Promises over the deep callback passing model from Part 1.

First, our function signatures are sane. We have removed the need to add callback and errback parameters to every function signature from the caller down to the XHR lib, and only the caller who is ultimately interested in the result needs to mess with callbacks.

Second, the Promise API standardizes callback passing. Libraries all tend to place callbacks and errbacks at different positions in function signatures. Some don’t even accept an errback. Most don’t accept an alwaysback (i.e. “finally”). We can rely on the Promise API instead of many potentially different library APIs.

Third, a Promise makes a set of guarantees about how and when callbacks and errbacks will be called, and how return values and exceptions thrown by callbacks will be handled. In a non-Promise world, the multitude of callback-supporting libraries and their many function signatures also means a multitude of different behaviors:

  1. Are your callbacks allowed to return a value?
  2. If so, what happens to that value?
  3. Do all libraries allow your callback to throw an exception? If so, what happens to it? Is it silently eaten?
  4. If your callback does throw an exception, will your errback be called, or not?

… and so on …

So, while one way to think of Promises is as a standard API to callback registration, they also provide standard, predictable behavior for how and when a callback will be called, exception handling, etc.

What about try/catch/finally?

Now that we’ve restored call-and-return and removed callbacks from our function signatures, we need a way to handle failures. Ideally, we’d like to use try/catch/finally, or at least something that looks and acts just like it and works in the face of asynchrony.

In Part 3, we’ll put the final piece of the puzzle into place, and see how to model try/catch/finally using Promises.

Async Programming Part 1: It’s Messy

Exceptions and try/catch

Exceptions and try/catch are an intuitive way to execute operations that may fail. They allow us to recover from the failure, or to let the failure propagate up the call stack to a caller by either not catching the exception, or explicitly re-throwing it.

Here’s a simple example:

In this case, getTheResult handles the case where thisMightFail does indeed fail and throws an Error by catching the Error and calling recoverFromFailure (which could return some default result, for example). This works because thisMightFail is synchronous.

Going Async

What if thisMightFail is asynchronous? For example, it may perform an asynchronous XHR to fetch the result data:

Now it’s impossible to use try/catch, and we have to supply a callback and errback to handle the success and failure cases. That’s pretty common in Javascript applications, so no big deal, right? But wait, now getTheResult also has to change:

At the very least, callback (and possibly errback, read on) must now be added to every function signature all the way back up to the caller who is ultimately interested in the result.

More Async

If recoverFromFailure is also asynchronous, we have to add yet another level of callback nesting:

This also raises the question of what to do if recoverFromFailure itself fails. When using synchronous try/catch, recoverFromFailure could simply throw an Error and it would propagate up to the code that called getTheResult. To handle an asynchronous failure, we have to introduce another errback, resulting in both callback and errback infiltrating every function signature from recoverFromFailure all the way up to a caller who must ultimately supply them.

It may also mean that we have to check to see if callback and errback were actually provided, and if they might throw exceptions:

The code has gone from a simple try/catch to deeply nested callbacks, with callback and errback in every function signature, plus additional logic to check whether it’s safe to call them, and, ironically, two try/catch blocks to ensure that recoverFromFailure can indeed recover from a failure.

And what about finally?

Imagine if we were also to introduce finally into the mix—things would need to become even more complex. There are essentially two options, neither of which is as simple and elegant as the language-provided finally clause. We could: 1) add an alwaysback callback to all function signatures, with the accompanying checks to ensure it is safely callable, or 2) always write our callback/errback to handle errors internally, and be sure to invoke alwaysback in all cases.

Summary

Using callbacks for asynchronous programming changes the basic programming model, creating the following situation:

  1. We can no longer use a simple call-and-return programming model
  2. We can no longer handle errors using try/catch/finally
  3. We must add callback and errback parameters to every function signature that might eventually lead to an asynchronous operation

We can do better. There is another model for asynchronous programming in Javascript that more closely resembles standard call-and-return, follows a model more like try/catch/finally, and doesn’t force us to add two callback parameters to a large number of functions.

Next, we’ll look at Promises, and how they help to bring asynchronous programming back to a model that is simpler and more familiar.

OOCSS Slides and More From the jQuery Pgh Meetup

I hope everyone who attended last night’s jBurgh meetup had as much fun as I did, and enjoyed my talk on OOCSS. I thought it was a great low-key event, and I have to say that the discussion after the presentation and hanging around talking to everyone were the best parts.

My slides are up on slideshare, and if you were at the meetup, I’d really appreciate your taking a minute to rate my talk, and (especially!) leave a comment about how it could be improved.

If you’re interested in getting more background on OOCSS, I encourage you to check out Nicole’s slides and video. I’ve also written a few articles that dig deeper into some of the concepts in last night’s talk, such as OOCSS inheritance, why .css() is bad, and OOCSS Antipatterns:

You can also check out the digital clock demo, including these other versions:

  • Analog – remember this is an antipattern (see above), no matter how cool it seems!
  • JQCon explode – we did this mod live onstage at JQCon
  • Daniel Lamb’s binary clock mod – he points directly to my JS view controller (view source to check it out), and just modded the HTML and CSS. Now that’s separation of concerns FTW.

For more deep diving along with some excellent code examples and comment discussion, I also recommend reading John Hann’s post on OOCSS for Engineers.

At the end of the presentation, I mentioned that I’m working on OOCSS design patterns for web applications. My plan is to post more information soon about the ones mentioned in the slides (with example code), as well as others, so stay tuned.

Thanks to Chris Bannon and Wijmo for organizing and sponsoring, to HackPittsburgh for lending us their space, and to everyone who attended! I had a blast, and I’m already looking forward to the next meetup.

OOCSS at the Next jQuery Pgh Meetup

I’ll be speaking about OOCSS at the next jQuery Pittsburgh meetup, this Thursday (2/3) at 6:30pm at HackPittsburgh. I’m planning to present some similar material as John Hann and I presented at jQCon in September, but I’ll also be including an expanded section on how to get started with OOCSS, as well as a section on OOCSS antipatterns.

Thanks to Chris Bannon from Wijmo for organizing the meetup, and for inviting me to speak. Hope to see you there!

Simple OOCSS Slideshows

I read this article recently, and decided to solve the problem the author proposes in point #3 using OOCSS techniques.

Here you go: OOCSS Slideshows.

You might be saying, “Good grief, all that CSS is overkill!”, and be tempted to think that just using image.style.display = 'none' is good enough. Try implementing those 3 effects in plain Javascript … you probably wouldn’t get it right—I know I probably wouldn’t.

Or maybe you’re thinking that you’d just use jQuery, Dojo, or your favorite effects library to do it. Putting aside the fact that the original interview question stipulated no libraries, the advantage of an OOCSS approach, as I’ve written about at length before, is separation of concerns, and all its related benefits.

Using an MVC and OOCSS approach puts control of the slideshow transitions into the hands of the designer, and changes to the transitions require zero Javascript changes.

Dojo Completion Statement Parsing

One of the things on my Dojo completion hitlist was handling multiline statements, especially dojo.query chains, since I tend to break them into multiple lines when chaining more than 1 or 2 NodeList function calls (and I’m betting most folks do that, too). While thinking about how to handle this, I came to the conclusion that there were basically three ways I could approach it:

  1. Implement a real Javascript parser that is liberal enough to handle incomplete statements (e.g. it has to handle the statement you’re trying to complete!), or
  2. Integrate an existing parser that is liberal enough to handle incomplete statements (I have no idea if a liberal open source JS parser exists), or
  3. Implement something simpler and easier that covers most or all of what I think of as common cases.

I decided to go with #3. In fact, this is my general rule of thumb for the completion bundle in the short and medium term. I want to make something that is both useful, and something I can actually release since I’m only working on it a few hours each week. An unreleased, vaporware completion bundle is far less cool than a released one that works 80% of the time.

Here are a few shots of the multiline statement parser in action, completing a dojo.querychain. Notice also, in the last shot, it guesses correctly that I am starting a new statement, even though I didn’t end the previous one with a semicolon. However, it’s not perfect, and will almost certainly break under less common conditions. I’ve tried, though, to abstract the parser from the completion code in a way that allows the parser to be improved when I find cases where it breaks.

 

TextMate Dojo Completions: dojo.require and dojo.query

Last week, I started thinking about what features I’d want in the TextMate Dojo completion bundle in order to feel good about calling it releasable. I made a list, and started knocking them down. Here are a few that I managed to tackle over the past week:

  1. It scans and executes dojo.require()s in the current file and adds their symbols to the completion context.
  2. It recognizes when you are typing inside a dojo.require() and completes dojo package names instead of functions and properties.
  3. It recognizes when you are in a dojo.query chain and completes NodeList functions while you’re in the chain.
  4. Because it understands both dojo.require and dojo.query, it will complete functions from NodeList mixins, such as dojo.NodeList-fx, that you’ve dojo.required in the current file.

How does it do that?

In a word: Javascript. I’ll be posting more about this later, once the first release is ready.

A note about performance

Any completion framework has to be fast. I’m ruthless when it comes to development tools, and I’ll bet you are too. If something slows me down, I stop using it. If the pain outweighs the benefits, it’s gone. So, one of my goals is to make sure this bundle is as fast as it can be.

The current performance is very good on my laptop. The completion popup is nearly instantaneous, even with dojo.require scanning, and hundreds of potential completions. That said, I’m using the most recent MacBook Pro rev with 8g RAM and an SSD. I realize that may not be the most common setup, so I will be testing it with other setups to make sure it doesn’t suck.

I can haz it?

A few folks have asked when they can get the bundle. Since it’s a side project, I don’t want to give a date. I’ll release an initial version when I feel it’s at the point that I’d actually use it, and I can tell you that it’s getting close :)

For now, here are a few more teasers that show the new stuff in action.

Dojo Autocomplete for TextMate

One of the biggest complaints I hear about TextMate is that it doesn’t have some sort of native intellisense, and doesn’t do code completion.  Those are typically features provided by “bigger” IDEs.  TextMate started life as a text editor, and has had different goals than other IDEs, so even though TextMate has grown closer to full-blown IDE over the past few years (thanks to lots of great community bundle contributions), it’s not really hard to understand why it hasn’t provide those features natively.

It turns out, though, that TextMate provides some builtin help for rolling your own completions, and a lot of folks have done that for various languages and platforms.  I decided to take a crack at it for Dojo as a part of a new, simplified Dojo bundle I’ve been working on.  Here are a couple teaser screenshots of what I have so far.

I’m not ready to post the bundle yet, but I’m actively working on it, so I hope to have an initial version ready within the next couple of weeks.

OOCSS Antipatterns: Analog Clock Theme Using Only CSS

You asked for it, and you got it. Several people asked me after the digital clock demo at jQCon if I thought it was possible to create an analog theme for the clock using only CSS. I had wondered this as well, but came to the conclusion that it was impossible, given the current HTML structure. So, that’s the answer I gave at the conference.

The very next day, I thought of a way to do it, so here’s an analog theme (source on github) for the digital clock done entirely in CSS.

First, note a couple things:

  1. The first hour, minute, and second digits are hidden.
  2. The second hour, minute, and second digits have been styled to look like analog clock hands—i.e. long thin rectangles, and have been anchored at the center of the analog clock face.

The key is the use (in fact, abuse, read on!) of the immediate sibling selector to rotate the clock hands to the correct position, using CSS3 transforms. For example, the line above says when the first hour digit is a “0”, and the second hour digit is also a “1” rotate the second digit (remember, it’s been styled to look like an analog clock hand) by 30°. Each hour represents 30° (360 / 12 = 30), so looking at the rest of the hour selectors, you can see how it works.

Similarly, the minutes and seconds are rotated using the immediate sibling selector. The only difference is the degrees, since 360 / 60 = 6° per minute/second.

Ok, neat, it works, but …

How not to build an analog clock

At this point, you’re probably saying to yourself (and if you’re not, you should be) “This is a terrible way to build an analog clock”. You are absolutely right. There are many problems with this, and I’d even go so far as to call the whole thing an antipattern.

From the HTML element hierarchy, to the CSS classnames, to the time computations, most everything tailored to represent an LED-based digital clock.

However, the point of this little exercise was not to find the best way to engineer an analog clock. The point was to answer the question “could it be done?”. But maybe we can learn something about OOCSS anyway.

There is something to be learned here

As the saying goes, “when all you have is a hammer, everything looks like a nail”, and in this case of trying to use only OOCSS to transform the digital clock into analog, there’s certainly some overly-ambitious hammering going on.

If the HTML is poorly-suited to the task at hand, trying to apply OOCSS on top of it will probably just make things worse. In fact, in this example, the HTML and CSS are fighting each other rather than working together.

OOCSS is not just about CSS, it’s about identifying objects in the view first (as John said in our presentation, “ignore the HTML!”), and then structuring HTML and CSS around the containers, content, identity, and states of those objects.

The fact is that the objects in this clock are LED digits, not analog clock hands, and some mildly clever CSS doesn’t change that. Conversely, this bastardization means that the hands of the analog clock have the classes “display-area” and “digit”, as well as “d0” – “d9”, none of which seem like logical choices for the hands of an analog clock!

Antipattern: In any reasonably complex system, writing HTML and CSS first is an antipattern.

What to do?: Break out the wireframes, gather around the whiteboard, and start identifying objects! List their states. Talk about ways to translate them into well-structured HTML containers and content.

One of the results of this object/HTML/CSS mismatch is state explosion, aka combinatorial explosion. There are 72 CSS rules needed just to rotate the clock hands, whereas there are only 10 rules for the original digital clock LED digits. That certainly qualifies as state explosion, and just looking at the analog rules should give you an uneasy feeling that something is wrong.

In fact, modeling any analog clock, not just this bad example of an analog clock, as discrete OOCSS states seems wrong. Consider also the progress bar example John gave during our talk. Progress bars, in most cases, represent a continuous function rather than a discrete function, and therefore can require an infinite number of states to model their possible values—e.g. 30%, 30.1%, 30.15%, and so on.

Antipattern: Trying to model continuous values with OOCSS state is an antipattern.

What to do?: Use a mechanism better suited to continuous values/functions, such as a vector library, or yes, even direct (but well abstracted!) style manipulation.

One other thing that should be bothering you about this analog clock is that nearly half the HTML elements are permanently hidden by the analog theme’s CSS. This can be an indication that you’ve misidentified the view objects. In this case, I think it’s pretty obvious that the objects I originally identified when creating the digital clock, that is, active digits composed of lit or unlit LED bars, simply are not present in the analog clock.

Antipattern: Having sections of permanently hidden HTML is an antipattern.

What to do?: Review your objects and wireframes. You may have misidentified some objects, or your application may have changed significantly enough over time that the objects you had originally, and correctly, identified are no longer present. Either way, it’s time to revisit the wireframes and refactor.

Trying to shoehorn an analog display into the digital clock was fun, but more importantly, I think it helped to identify some OOCSS antipatterns. Hopefully these will help us all avoid some pitfalls!