Sunday, November 27, 2005

REST Revisted

I never did finish off blogging about REST. Well, where I got to in my understanding is that REST is all about state transfer. Moving and changing state between distributed application components in an asynchronous way. To support state transfer REST has a small number of fixed verbs: GET, POST, PUT, DELETE etc. Along with defining the type of state in question (MIME), and the location of that state (URI), thats all you need for state transfer.

My interest is object orientated distributed programming. Well with no new verbs, object orientated messaging is out of the question with REST (look back at my post about sending the message "deleteStuff" using HTTP GET). So for OO the only RESTful option is object transfer (code on demand).

This is cool for an application that is basically asynchronous in nature. What happens though when you need synchronised transactions, say for Croquet? I posted this question on the REST discussion group back in October and I'm still waiting for a reply:

http://groups.yahoo.com/group/rest-discuss/message/5347

REST is also about constraint, and the REST constraints just don't allow for messaging. Objects contain state hence RESTful "code-on-demand" is possible, but they also contain behaviour which is selected through messages (verbs). Message sending is not possible with REST. So replicating objects across several clients and coordinating their behaviour using transactions as required in Croquet just isn't possible with REST (IMHO).

It would be interesting to hear from anyone who thinks otherwise.

In agile development there is a saying "The simplest thing that can possibly work, but no simpler". For state transfer of static and semi-static web content then REST is that simplest thing. For interactive and dynamic multi-user transactions, such as in Croquet (or online shopping/auctions?), REST just doesn't cut it IMO. So it turns out that REST (http) is what I've allways intuitively felt it to be, a limited protocol for a limited set of applications.

1 comment:

Paul said...

Mark baker begs to differ. Here i a copy of e-mail correspondence between Mark and Myself:

On 12/1/05, Paul Beckford wrote:

>> Thanks for the presentation. Interesting that you say the XML above
>> implies an operation. To me objects have both state and behaviour
>> (operations). It is advantageous at times to instigate operations
>> without knowing state:


Behaviour doesn't mean object-specific operations. consider ...


>>
>> turtle.turnEast()


PUT http://example.org/myTurtle/direction
<east/>

>> turtle.moveForward(5)


POST http://example.org/myTurtle/movement
"5"



>>
>> These operations say nothing about state, whilst:

>>
>> turtle.Xposition
>> turtle.Yposition
>>
>> exposes the cartesian state of my turtle.


Which could be PUT to, yes, even as an aggregate, e.g.;

PUT http://example.org/myTurtle/position
<pos>
<x&>10</x>
<y>5</y>
</pos>

But PUT can't be used to "move ahead 5" since ahead is relative to the
current state ... unless you wanted to GET, calculate the new position
yourself, then PUT it; but that's a different form of transaction when
compared to an atomic "move ahead 5" that may not be suitable in all
cases... hence the need for POST.


>> With objects I do not need to
>> know the state representation, because it can be hidden behind operations.


OO doesn't require object specific operations. It (normally) is
understood to requiring at least encapsulation, which means to keep
related data together, bound to the object identifier. Data hiding is
often eschewed nowadays, and used to be confused with encapsulation.
Polymorphism's good though, but resorts to a degenerate form of itself
(late binding) when used in conjunction with a single interface.


>>
>> so ..
>>
>> turtle.r
>> turtle.theta
>>
>> Using bipolar coordinates is an equally valid representation and
>> supports the operations "turnEast()" and "moveForward(5)" equally as well.


Sure. And so for the absolute move, you could also do;

PUT http://example.org/myTurtle/position
<pos>
<r>10</r>
<theta<1.7</theta>
</pos>

>> Being true to the semantics of rest doesn't seem to allow for this kind
>> of data hiding.


The word "representation" in REST means that encapulation isn't
broken, because the client need not be exposed to the "true state" of
the resource/object; it's only exposed to a "copy" of the state, in
various forms (media types). Just as getFoo() doesn't break
encapsulation so long as a copy of Foo is returned, not a pointer to
the internal Foo.

As above, data hiding != encapsulation though. REST is completely
anti-data-hiding, but entirely pro-encapsulation.

Mark.
--
Mark Baker. Ottawa, Ontario, CANADA. http://www.markbaker.ca
-->

Mark has a point. There is a subtle semantic difference between RESTful OO messaging and traditional OO. To be RESTful the message must identify a resource e.g. "Movement" instead of an operation "moveForward". So you need to change your messages from verbs to nouns. Does this matter? I think so. There is a cognitive differnce between a verb and a noun. Limiting your volcabulary to just nouns IMO reduces the expressiveness of your objects.

A compromise is to map verbs to nouns using annotations e.g

class Turtle {
<HTTP op="PUT" resource="movement"/>
void moveForward(int dist) {
...
}

A RESTful library supporting this approach would be interesting.