Archive for April, 2008

The Shadow of a Legacy

Sunday, April 20th, 2008

Update: I got my facts wrong, to an extent that makes my thesis wrong too. See the comment that begins “Well Vista dropped dos and win16”.

In software, an internally disruptive change is one where backwards compatibility is a major concern for the developing organization at the architectural level (and not just a matter of larger matrices in QA). It’s disruptive because it takes a drastic change to the architecture to cause this degree of disruption; it’s internally disruptive because, when compatibility is a requirement, the effects of the disruption are moved inside the development organization.


Read the rest of this entry »

Minimizing Code Paths in Asychronous Code

Sunday, April 20th, 2008

Have you ever written a function that looks like this?

[code language=”javascript”]
function requestProductDetails(id, k) {

var value = gProductDetailsCache[id]; if (value) k(value) else ajax.get(’/product/’+id, function(data) { gProductDetailsCache[id] = data; k(data); });
}
[/code] requestProductDetails calls its callback with the product details, which are stored in a cache. Since it might need to request this information from the server, it has to “return” it by passing it to a callback; in order to present a uniform API whether or not the product is cached, it “returns” the data this way whether it came from the cache or not.
Read the rest of this entry »

A Mock for {set,clear}{Timeout,Interval}

Sunday, April 20th, 2008

Here’s a potential JSSpec spec for Sequentially.trickle.map:

[code language=”javascript”]
describe(‘Sequentially.trickle.map’, {

‘should apply to all the elements’: function() { Sequentially.trickle.map( [‘a’, ‘b’, ‘c’], function(x) { return x + 1 }, 1, function(result) { value_of(result.join(’,’)).should_be(‘a1,b1,c1’); }); }); }
});
[/code]

This doesn’t work. The problem is that Sequentially.trickle.map is asynchronous (it defers most of its computation – including the invocation of the callback – via setTimeout). This means that should_be isn’t called until after the spec has returned. If it succeeds, this isn’t a problem, but if it fails, JSSpec can’t associate it with the failing spec – worse, JSSpec will have already have marked it successful.


Read the rest of this entry »

Conquering the Busy Cursor with Sequentially

Sunday, April 20th, 2008

What’s wrong with this function? (Hint: it’s meant to execute periodically on a JavaScript page.)

[code language=”javascript”]
function updateExpirationText() {

var now = new Date; products.forEach(function(item) { var expiresDate = item.expiresDate || Date.parse(item.expires), remaining = expiresDate - now, text = remaining < 0 ? ‘expired’ : msToDuration(remaining); $(‘item-’ + item.id + ’ .time-remaining’).text(remaining); });
}
[/code]

It’s a trick question. Maybe nothing’s wrong. But if products can get very long, or if the msToDuration is very slow, you’ve locked up the UI for a long time. At best, this makes for sluggish response; at worst, the page that contains this will trigger a “script running slowly” error, and the user will likely abort all the JavaScript on the page.


Read the rest of this entry »

DB Content Rails Plugin

Thursday, April 17th, 2008

The DB Content Rails plugin adds tasks to save and restore database content.

Usage

[code]

– dump the development database to db/archive/development-content.sql.gz
rake db:content:dump – load the dumped database, and apply any necessary migrations
$ rake db:content:load – dump the production database to db/archive/production-content.sql.gz
$ RAILS_ENV=production rake db:content:dump – save the development database to db/archive/{timestamp}.sql.gz
$ rake db:content:save – save the (compressed) database to my-data.sql.gz
$ rake db:content:save FILE=my-data.sql.gz
Read the rest of this entry »

JCON: Ruby Gem for JSON type conformance

Thursday, April 17th, 2008

JCON (the JavaScript Conformance gem) tests JSON values against ECMAScript 4.0-style type definitions
(PDF) such as string?, (int, boolean), or [string, (int, boolean), {x:double, y:double}?].

Usage

[code language=”ruby”]
type = JCON::parse ”[string, int]”
type.contains?([‘a’, 1]) # => true
type.contains?([‘a’, ‘b’]) # => false
type.contains?([‘a’, 1, 2]) # => true
[/code]

JCON also defines an RSpec matcher, conforms_to_js:


Read the rest of this entry »

Three Small JavaScript Libraries

Tuesday, April 15th, 2008

Three small libraries, that I carry with me from project to project:

Fluently – Construction Kit for Chainable Methods

With Fluently, you can do this:

[code language=”javascript”]

var o = Fluently.make(function(define) { define(‘fn1’, function() {console.info(‘called fn1’)}); define(‘fn2’, function() {console.info(‘called fn2’)}); define(‘fn3’, function() {return 3}); });
[/code]

to define an object with chained methods, that can be invoked thus:

[code language=”javascript”]

o.fn1().fn2() // calls fn1 and then fn2 o.fn2().fn1() // calls fn2 and then fn1
Read the rest of this entry »

JavaScript Fu Rails Plugin

Monday, April 14th, 2008

JavaScript Fu extends Rails with a few facilities to better integrate JavaScript into Rails development:

1. The notes and statistics rake tasks compass JavaScript files in the public/javascript directory:

[code language=”bash”]
$ rake notes
public/javascripts/controls.js:

* [782] [TODO] improve sanity check
[/code]

[code language=”bash”]
$ rake stats

| Name | Lines | LOC | Classes | Methods | M/C | LOC/M |
[...]

| JavaScript | 7287 | 6322 | 0 | 0 | 0 | 0 |
[...]
[/code]

2. The call_js RSpec matcher asserts that a string or response contains a script tag, that contains JavaScript that calls the named function or method:


Read the rest of this entry »

FlashBridge: proxying Flash <-> OpenLaszlo

Sunday, April 13th, 2008

I’ve updated my OpenLaszlo utility grab-bag to make browser <-> applet communication even easier. How easy?

Proxies

Put this in your browser JavaScript:

[code language=”javascript”]
var gObject = {

f: function() { console.info(‘gObject.f’, arguments) }, g: function() { console.info(‘gObject.g’, arguments) }
};
[/code]

And this in an OpenLaszlo applet:

[code language=”javascript”]
var gObject = FlashBridge.createRemoteProxy(‘gObject’, [‘f’, ‘g’]);
gObject.f(1, 2);
gObject.g(3);
[/code]

When you run the applet code, it prints this to the browser console:


Read the rest of this entry »