Thursday, March 10, 2005

Thinking Out Loud - The Pain of Developing Bad Ideas

The problem with XUL & XMLHttpRequest is that XMLHttpRequest is not well suited to the transmission of server-side objects to the client-side ones. JPSpan fails miserably at what it does because of the lack of implicit sessions, the complexity involved, and the lack of queing and threading on the client side. This is no fault of the developers, they've done a great job at implementing a bad idea - and it seemed so right initially.

What we need is a language neutral intermediate data format. XML you say. Too easy. But the differences between Javascript and PHP clash far too much that though a PHP object goes into XML, a different, far more crippled object comes out in Javascript.

Both PHP and Javascript are all about doing one thing at a time. But Firefox has problems that interfere with the UI if you try to do synchronus XmlHTTPRequest connections, so you have to step into the world of Asynchronus connections. This is where the problems get worse. Callback functions. JPSpan relies on anonymous functions in callback handler varibles. Thus, you can't go: var mySale = new Sale(); alert(mySale.getTotal());. You have to rely on a function in two parts:


var handler = {
getTotal: function(result) {
alert(result);
}
}

function sell() {
var s = new Sale(handler);
s.getTotal();
//there is no way in this function to get the result,
//without resorting to global varibles.
}



That's incredibly more intricate than:


function sell() {
var s = new Sale(handler);
alert(s.getTotal());
}


Which is what we know and expect.

So, how do other AJAX applications manage broking objects where I'm failing?

Google's Gmail uses a UI engine which speaks javascript as the intermediate language. The server spits out javascript objects, there's no intermediate XML which makes us lose information in translation.

More 'traditional' web services (as this is all that we are really trying) do fine with RESTful interfaces and spitting XML at each other. There's a controlled and defined vocabulary, the server does their own thing, spits it out in hardcoded XML, and lets the client deal with the mess. This was the path I first started on, and I ditched it because when it got down to it, I was trying to pass strings about as my messages - messy, and I needed to pass more than one bit of information at a time.

PHP automagically understands GET and POST form submissions. XML via GET/POST as a restful service (ala musicbrainz) is an extra layer of abstraction ontop of that - but one we can deal with at the cost of losing our automagic varible parsing.

After writing this post, which was to entirely rethink the problem and forget that I'm screwing up quickly, I've realised that JPSpan isn't the way - the ideas are right, the implementation is too tangled. XUL, XMLHttpRequest, REST, XML. Well defined and controlled spec to start from. Evolves to meet real world implementations.

I recall initially I wanted RDF/XML over REST, but I abandoned this because RDF parsers in javascript where either closed to me (firefox security prevents me using the internal one) or not fully implemented (sorry Jim :/). How about RDF/XML over REST, parsed as XML by the client application, but more stable clients (like java ones!) could use RDF/XML to conduct transactions? I think I like that idea.

Next stop: Square One.

2 comments:

Anonymous said...

Hi - I'm one of the JPSpan developers.

On the one hand I agree that there's some serious issues with the whole notion of "AJAX" (which I'll get to) and also agree that the fundamental premise of JPSpan may also be flawed - that there may be another way of thinking about the problem which solves it better.

One thing in particular though, that I need to point out;

"But the differences between Javascript and PHP clash far too much that though a PHP object goes into XML, a different, far more crippled object comes out in Javascript."

First the encoding of data is different, depending on the direction you're going. From Javascript to PHP it does use XML to encode data, by default although it's also capable of generating strings ready for PHP's unserialize function, but this only works for ASCII characters. XML was the next easiest thing to implement, as it's fairly easy to parse in PHP.

In the PHP to Javascript direction it's doing something similar to Gmail and Google Suggest - generating Javascript itself which is eval'ed on the client side - this is alot faster than using XML and gives more power. The Sourceforge project search example (http://jpspan.sourceforge.net/wiki/doku.php?id=examples) in particular, demonstrates how to send not only data but "behaviour" (a function attached to the data) from PHP to Javascript.

Otherwise;

"JPSpan fails miserably at what it does because of the lack of implicit sessions, the complexity involved, and the lack of queing and threading on the client side."

At the first attempt, didn't want to get into implementing any of that. First because it's alot of effort and second because I'm only just starting to see how to implement these things in a manner where "one size fits all".

Right now JPSpan is suitable, in unextended form, to responding 1-to-1 with actions a user performs in the UI - i.e. "Clicking Save" = "One HTTP Request" - and if it fails either you report that to the user and reattempt the request in the code. If you want something like threading, sessions, reliable messaging etc., you have to implement it yourself - JPSpan is only focused on getting data from A to B.

In particular, the issue you mention with what's expected, codewise, on async requests can't be solved easily unless implementing something like threads in Javascript. I've seen it attempted here http://fm.dept-z.com/ and may try to bring that to JPSpan. At the same time, it may turn out to be easier to work with callbacks than threads.

Also looking at HTTPLR (http://www.dehora.net/doc/httplr/draft-httplr-01.html) as a means for reliable messaging over HTTP. But that's alot of implementation both client and server side. With reliable messaging should come queueing.

As far as sessions goes, think XMLHttpRequest redefines the meaning of what a session is in a web application. In one sense, until you hit reload, that page using XMLHttpRequest is your session. At the same time, browsers still handle cookies transparently with XMLHttpRequest and as this example shows: http://blog.joshuaeichorn.com/archives/2005/04/19/ajax-hello-world-with-jpspan/ using PHP's $_SESSION variables is no problem.

Like I say, my view of how to do this stuff may be fundamentally floored and perhaps there is some far cleverer way to do this stuff, if we stop thinking in terms of RPC. That said, as I see it the whole AJAX debate has glossed over the nature of HTTP and that there's certain things you cannot workaround, in particular;

- The server cannot call the client. The client always initiates the "conversation"

- The network is unreliable (no really unreliable not just Saturday nights)

The only way I can see around that is with alot more code (like reliable messagine) - I don't see some amazing paradigm shift that makes this go away.

The acid test, as I see it, is how you manage display and editing of a list of users with XMLHttpRequest?

Some particular crunch issues;

- How do you keep network requests to the minimum (i.e. one request per list vs. one request per user in the list) so performance remains acceptable?

- How do you keep client side resource usage to a minimum? Better they deal with a paged result set rather than the entire list of users. What if a row get's inserted at the top of the list while they are paging?

- If someone "edits" a user, how do lock that record so no one else can edit it, until the change is complete?

- How do you make sure changes are guaranteed delivery (what if the network was down)?

- How do you make sure that multiple clients are seeing the most up-to-date information in the list?

Think all of that can be done but actually doing needs alot more code.

Dan said...

Hey!
Cool, JPSpan developers reading my rants!

First off: by no means do I mean to bash your work - it's far, far beyond my megre skills to do!
You've done wonderful things with the tools browser vendors have provided, and I'm in awe.

"Right now JPSpan is suitable, in unextended form, to responding 1-to-1 with actions a user performs in the UI - i.e. "Clicking Save" = "One HTTP Request" - and if it fails either you report that to the user and reattempt the request in the code. If you want something like threading, sessions, reliable messaging etc., you have to implement it yourself - JPSpan is only focused on getting data from A to B."

You notice this so much when you are developing server side based XUL applications - unless you have your shit together (which I did not), you are going to have a bad time getting things working. Fluidly.

The idea of JPSpan is wonderful; but unless clients run PHP or servers run on javascript, I think it's never going to be utterly clean, simple, and end user friendly.
Neither of those two strike me as an option, either.

Artificially adding in threading to javascript... in javascript... strikes me as something inducing yet more complexity.

You're right about Gmail & Google maps, too. The thinking needs to be done on the server, where you have the power, rather than on the client, where you have to talk in a language that lacks many powerful features.

I'm still keeping tabs on JPSpan and I'd love it if you guys cracked these problems over the head with a big, PHP shaped club. Repeatedly.