Saturday, February 23rd, 2008

Ojay – a chaining wrapper for the YUI

Category: Ajax, Programming, Yahoo!

<p>JavaScript is a language that can be approached from many angles. Historically it was UI-driven web developers that started playing with it, but lately and with the advent of large JS applications “the world’s most misunderstood programming language” is also written by people that feel much more at home in higher programming languages. The nature of JavaScript then can become a barrier for fluid and rapid development.

This is where in the best of cases developer specialization comes in – which is not cheap. Another way to tackle the issue is to use metaprogramming to make the end language behave in the way you want it to.

James Coglan got inspiration from Dustin Diaz’ DED|Chain and wrote a chaining wrapper for the the YUI‘s DOM, event, animation and Ajax modules called Ojay.

He wraps up his intentions thus:

To me, expressiveness is not just ’syntactic sugar’, a tool to help you type fewer lines of code. It’s a core factor in how maintainable and well-designed your codebase is. We have a team made up of Java devs, a few Ruby enthusiasts and a couple of JavaScripters, and it’s crucially important to us that anyone can look at a piece of code and figure out what it does. Code should tell a story.

What this translates to is shown in this example:

javascript
< view plain text >
  1. $('a#run-this-code').on('click', $.stopEvent)
  2.     .setContent('Running...')
  3.     ._('#example').animate({
  4.         height: {to: 0},
  5.         opacity: {from: 1, to: 0}
  6.     }, 0.5)
  7.     ._($.HTTP).GET('/service/hello.html')
  8.     .insertInto('#example')
  9.     ._('#example').animate({
  10.         height: {to: 80},
  11.         opacity: {from: 0, to: 1}
  12.     }, 0.7);

I am not sure about the morale of this story, but I can see that we will see more and more of this sort of metaprogramming and skillset mash-up happening in the nearer future. Therefore it is great to start conversations early about how to tackle multidisciplinary teams writing code.

Posted by Chris Heilmann at 6:55 am
13 Comments

+++--
3 rating from 49 votes

13 Comments »

Comments feed TrackBack URI

I’m not sure about the morale of the story either, but I’m quite sure its different from its moral.

Comment by skippyK — February 23, 2008

Personally, I agree that code should tell a story; in other words: be self-explainable. But I do believe that, while superficially a good idea, chaining functions has serious downsides in that respect, as well: just like a story, code should be formatted for readability. When chaining functions, this readability gets a good kick because of all the punctuation and syntax characters.
Look at the code posted:

$('a#run-this-code').on('click', $.stopEvent)
.setContent('Running...')
._('#example').animate({
height: {to: 0},
opacity: {from: 1, to: 0}
}, 0.5)
._($.HTTP).GET('/service/hello.html')
.insertInto('#example')
._('#example').animate({
height: {to: 80},
opacity: {from: 0, to: 1}
}, 0.7);

And some pseudo code:

var e = lib.select("a#run-this-code");
var ex = lib.select("#example");

lib.setContent(e, "Running");

lib.animate(ex, {
height: { to: 0 },
opacity: { from: 1, to: 0 }
}, 0.5);

var dat = lib.get("/service/hello.html");

lib.insertInto(ex, dat);

lib.animate(ex, {
height: { to: 80 },
opacity: { from: 0, to: 1 }
}, 0.7);

Which one has a high degree of readability? I’d wager the second one, at least, in a glance. Yes, chained code is just as self-explanatory, but it’s my experience that when I’m scanning a document with lots of chained coding, the reading speed suffers considerably because of all the punctuation and characters.

Comment by DiSiLLUSiON — February 24, 2008

Oh by the way: I’d personally change the object variables passing to a function as well — since it degrades readability as well (not to mention how many times people forget to correctly put a , after the line in an object except the last one) — to a string like “height=80,opacity-from:0,opacity-to:1″;

Comment by DiSiLLUSiON — February 24, 2008

I forgot to post the pseudo code:

var e = lib.select("a#run-this-code");
var ex = lib.select("#example");

lib.setContent(e, "Running");
lib.animate(ex, "height-to:0,opacity-from:1,opacity-to:0", 0.5);

var dat = lib.get("/service/hello.html");

lib.insertInto(ex, dat);
lib.animate(ex, "height-to:80,opacity-from:0,opacity-to:1", 0.7);

The more readable your code is, the easier it is to maintain by multiple developers and especially new developers.

Comment by DiSiLLUSiON — February 24, 2008

Not bad this might ease the transition from a jQuery project to a YUI one, however I would worry about this project not keeping up to date with YUI and it becomes harder to upgrade.

I could see myself using jQuery accidentally with this. :-x

Comment by Tr0y — February 24, 2008

If I could correct one small misaprehension: the chaining in Ojay is more powerful than that in jQuery, in that it handles asynchronous behaviour for you rather than just calling a sequence of methods synchronously on the same object. If I were to rewrite the example without chaining, it would need to look like this:


$('a#run-this-code').on('click', function(link, e) {
e.stopEvent();
link.setContent('Running...');
var example = $('#example');
example.animate({
height: {to: 0},
opacity: {from: 1, to: 0}
}, 0.5, {
after: function() {
$.HTTP.GET('/service/hello.html', {}, {
onSuccess: function(transport) {
example.setContent(transport.responseText);
example.animate({
height: {to: 80},
opacity: {from: 0, to: 1}
}, 0.7);
}
})
}
});
});

I’ve run into plenty of examples where the nesting gets so deep the flow of the code is completely intractable, so I wanted to come up with something that made it clear which order things are happening in. Also, using chaining rather than nested functions, setTimeouts etc means if you want to remove one of the steps, you only need to modify the code in one place rather than two or more.

I know the example is not particularly elegant, but I wanted to demonstrate several concepts — events, ajax, animation, asynchronous chaining — in one short snippet. Hopefully the other examples through the documentation are better examples of style.

Comment by James Coglan — February 24, 2008

This is one case where syntax highlighting, for me, gets in the way. I find the non-highlighted version on the original page very easy to read, but here I’m distracted by the way the color breaks up the flow.

Comment by michaelhart — February 24, 2008

I was going to say.. “this is what DED|Chain was.” But now that I know it got the inspiration from it, I feel better now :)

Comment by ded — February 24, 2008

James Coglan: I see your point. Though the extreme indenting in your ‘flat’ example can be averted when the anonymous functions are defined beforehand, it does distort the ‘flow’ extremely:


var example = $('#example');

var before = function(link, e) {
e.stopEvent();
link.setContent('Running...');
example.animate({
height: { to: 0 },
opacity: { from: 1, to: 0 }
}, 0.5, { after: getstuff });
};

var after = function(transport) {
example.setContent(transport.responseText);
example.animate({
height: { to: 80 },
opacity: { from: 0, to: 1 }
}, 0.7);
}

var getstuff = function() {
$.HTTP.GET('/service/hello.html', {}, { onSuccess: after })
};

$('a#run-this-code').on('click', before);

Quite readable, however, naming those functions isn’t really a good idea…

While (judging on your examples) Ojay does a good job of increasing the readability of the code, compared to YUI, while retaining a ‘natural’ flow, how far are you willing to take it? It’s not bad, but it’s not perfect either. That’s basically the point I tried to make: While chaining is one thing, how about using strings and .toSource() them into objects to feed YUI when an object will never contain a function? Perhaps even create wrappers with a few parameters for often-used combinations (like the example on your frontpage) so there’s even less typing?

Comment by DiSiLLUSiON — February 24, 2008

Oh, the asynchronous behavior is a big plus: very cool.

Comment by DiSiLLUSiON — February 24, 2008

…Very cool indeed: I’ve been reading the link you provided, and it does a better job of explaining Ojay then this post on Ajaxian does. I kinda missed the point: thought it was about readability concerning the syntax, but it’s not. It’s about readability concerning the structure! In that case, please disregard my earlier posts. :)

The way it flattens out async behaviour is quite good, since it makes the ‘flow’ of code much easier to grasp at a glance. Nice.

Comment by DiSiLLUSiON — February 24, 2008

I would still like to be able to write this though:


$("a#run-this-code").on("click", $.stopEvent)
.setContent("Running...")
._("#example").animate("heightTo=0,opacity=1:0", 0.5)
._($.HTTP).GET("/service/hello.html")
._("#example").animate("heightTo=80,opacity=0:1", 0.7);

Oh well, I can dream, can I not?

Comment by DiSiLLUSiON — February 24, 2008

I was going to say.. “this is what DED|Chain was.” But now that I know it got the inspiration from it, I feel better now :)

Comment by irinasheik — December 15, 2010

Leave a comment

You must be logged in to post a comment.