CoolAJ86

Thursday, May 06, 2010


My question: how do you organize JavaScript code? How do you add OOP
features to JavaScript? How do you separate DOM-manipulation from
business logic in JavaScript?




Object Oriented, Event and Message Driven, Asynchronous Non-Blocking Programming

First, I recommend reading this article by google How to Think About OO [1]

I believe the reason that JavaScript code is less "intuitive" to organize is because, well, we've been trained to program in ways that are less intuitive. Like a Windows user switching to a *nix (Mac or Linux) - the simplicity and elegance of the paradigms of solutions can be hard to wrap your head around at first, even intimidating.

JavaScript provides a valuable learning opportunity. It thrusts a different (perhaps more elegant) paradigm on us - that of asynchronous (or event driven) programming as opposed to procedural programming (which we tell ourselves is object-oriented, but if you contrast any OO code you've written with the paradigm discussed in How to Think About OO, you may well find that you're not actually using your objects as objects).


Normally we want to write procedurally:
friends = Friends.getAll();
doStuff(friends);

In some other language, such as ruby or python, Friends.getAll() would likely be asynchronous blocking call to a database which should complete in some matter of fractions of a second. In past generations of programming we accepted this waste of processor time and such because it wasn't very noticeable and we have had the liberty of scaling out - buying more systems to make up for the loss of availability that we don't even realize we could have.

However, in JavaScript we don't have the luxury of procedural programming, nor of scaling up. We have to use the one machine that we have to the maximum value that we can. We don't use synchronous blocking calls because a call to a web service (such as Amazon with which you must perform several iterative queries to get the data you're looking for) could take several seconds - perhaps 10 or more - before you have the data you want.

jQuery comes along and makes AJAX and AJAJ (JSON) easy. But then, if you're like me, you find yourself in this tangled web of callbacks. It becomes less clear how to organize code.

So now you have something like this:
// Get all Friends <-- Note that you've lost the ability to create self-documenting code here
$.get('http://webservice.com/friends' + '?callback=?', function(){
    // do stuff <-- and here as well
    ...
})

The problem here is that there's more than one type of doStuff() that you might want to do with your friends. You don't want to make a call to the webservice each time so you might store friends in an html5 datastore or a friends variable in memory. You might choose to halt some execution of your program until you get friends back. But then you're synchronous blocking again!

How do you know when you've already gotten friends? How to you update friends reliably?
It would be nice if we could have a hybrid of the two (such as Ruby's Fibers) [2] such that calling an asynchronous function would pause execution of the current code (and thus allow other events to take place during the non-blocking wait) and then continue with the execution of the code.
friends = $.get('http://webservice.com/friends')

But that's just not possible in javascript as of today.


The solution I see is to treat each object as an application until itself, with it's own MVC and "pass messages" rather than "call functions" (something I've learned from ruby).

Scenario:
I have button in a facebook app which will display the 10 friends with the closest upcoming birthdays.
I'm allowed to cache the urls of pictures of friends as well as profile data for 24 hours.
I must initially get the data from facebook, but I cache it in an html5 data store.

Friends.send( { "message" : "with_birthdays", "conditions" : { "quantity" : "10" }, "present_as" : "#friends_with_birthdays")

or perhaps more practically:
Friends.extend({"presenter_class_name" : "Template", "message_map" : { "with_birthdays" : "friends_with_birthdays" } })
Friends.with_birthdays({"quantity":10})

This way the data lives with the object as described in How to think about OO [1]. The callbacks all take place within the Friends object and the Friends object will send a message to use the "#friends_with_birthdays" template on some hash object - probably with a timestamp as to when the message was received.

And perhaps by the time that the data is retrieved the user has chosen to view something else. The Presenter (template class) may have some logic to help it decide how to ignore stale messages or the Friends class may be able to be modified such that at each callback step it checks to see if the action has been cancelled. If it has, it doesn't send the message to the template class at all.


Do you find this to be helpful? I'd appreciate your feedback and ideas, as I'm still trying to figure this out for myself.



AJ ONeal

Recommended Reading / Viewing:
[3] Best Ideas in JavaScript Development: http://cdn.javascriptmvc.com/videos/2_0/2_0_demo.htm