Monday, July 28, 2008

Putting REST to rest

... or Why Implied Interfaces make for poor Implementations.

Representational state transfer (REST) is a style of software architecture for distributed hypermedia systems such as the World Wide Web.
- from Wikipedia

The term REST along with the principles it implies (or 'should' imply!) were put down in a doctoral disseration by Roy Fielding.

Actually IMHO, REST is just SOA and WS wrapped in a layer of OOP with just a generic Resource entity at the application layer. Even then, you kinda get to roll your own with everything- serialization, interaction, responses, validation...

Well... OK, I may have over-genericised that. But, the funny thing is, that's the funny thing about REST! It is very generic.

Even the primary 'Resource' definition is vague; the interface is almost completely implied-
  • POSTing to a URL creates a new resource (POSTing what?!)
  • I GET a resource referenceable at a given URL provided an id, otherwise... I get all resources at that URL (?); unless, of course, it is a singleton resource, in which case I get the singleton instance. :S
  • PUTting causes edits, although POSTs may behave in the same manner
  • HEADs can be used to detect the presence of a resource, while DELETEs... delete![1]
  • And I'm not even sure if OPTION and TRACE are relevant
And that's just REST over HTTP! Wait!! Is there any other REST?!? Well actually REST is a meta-architecture, it's protocol-agnostic. It's supposed to work for all hypermedia- so we should be able to do it over HTTP, FTP, SMTP, SNMP(?)...

What is hypermedia? Media hopped up on too much sugar?!? Well, the Oxford Dictionary defines it as
an extension to hypertext providing multimedia facilities, such as sound and video.
I don't know about you, but my brains just about ready to explode.

But wait, it gets better. Some people liked the REST over HTTP idea so much that they forked their own flavour. So Fielding has Vanilla, while (these guys) have Extra Fudge! (all puns intended) It's called Web-Friendly services- services that behave reeeeally well with HTTP. Basically services that behave like web pages. Whoa! I'm getting asmx flashbacks!!! So I'm gonna shut up about that now.

Then there's the Hypermedia As The Engine Of State Transfer people[2]. These guys really love the URL. To them the body is whatever it's gonna be! Now it's an XML document, now it could be a HTML FORM, then it could be a JSON object or, maybe, a hCard. I'm sorry, but I can't comprehend this comically 'uniform' interface where your interaction modes are implied, reference end-points are overloaded and results are undefined, or implied, or... did you say they're documented somewhere?

The question I arrive at, then, is- why do we want to be RESTful or Web-Friendly? The loudest argument I hear is that the infrastructure has has already been laid; web servers and proxies with caching, DNS servers, IP routers with path optimization algorithms, the whole kahuna! Think of all the automatic performance gains arising from all that caching! All the more reason to stick more stuff into the URL and fill up those HTTP parameters you never thought to use until now! You just ride the wave!

Hmm... it would seem that REST intends to counter the end-to-end principle by allowing for intelligence (optimizations) at the nodes, but that's a little too debatable; so <sidestep />.

But stepping back a bit, lem'me get this right. We're trying to fit an application protocol directly over a document delivery infrastructure? You've gotta be kiddin' me! I'm not saying this can't be done, just not without a cost- TANSTAFL. Just think about all the time you're going to spend on deciding and negotiating a wire format, and corresponding responses. And that's just one wire format. REST talks of 'representations', a resource could have more than one wire format! I don't know about you, but I've had trouble getting people to understand one wire format right, and now you're telling me they're gonna want to send 'resources' in XML, JSON, YAML, HTML, delimited strings, multi-fixed and EBCIDIC? Over my dead body!!!

Plus, the wireformats are completely arbitrary. Every resource implementer gets to pich their own. So you end up having to 'understand' the specific wire format of every resource you interact with. And by 'understand' they mean RTFM. So much for convention over configuration. Just too much Knowledge in head vs Knowledge in world.

Actually, the wire format is where it gets really funny. XML just had the attribute-element dilemma, REST elevates it to the payload-parameter dilemma! Most Web-Friendly service makers get away without a body to the requests, they just stick a bunch of 'required' HTTP parameters on to the resource URL. So much for 'representation' of 'state', we're back to representation of output. Why does this remind me so much of WS?

I think REST could find application in internal applications where the domain model is well defined, where resources and their interactions are well defined. But I'd still be skeptical because I tried that once at work and we kinda crashed and burned. The biggest brick wall we hit was latency. Given the 'resource' unicycle that REST provided and the specific verbs HTTP provided made our resource interactions multi-stage, especially since REST is stateless. When updating a resource, I wanted to GET a representation of the current state of the resource, modify it and PUT the modified state representation back into its place. But others on the team felt that adhering to those principles added unnecessary communication overheads and chose to add interaction verbs, which was conveniently provided for by ActiveResource. Oh, and that's just when we were not arguing about the wore formats.

Honestly, if you ask me, the only reason REST wont go down the tube like Hailstorm is because it's community driven, not governed and controlled by a megalomaniac. Everyone gets to roll their own and even fork while still calling it RESTful. But even if it does last, I think it's only going to be a buzzword that we'll all have a good laugh about in a few years-

Raj: Hey Saager, we're building this new service for so-and-so and it's accessible via, get this... RESTful resources! :D
Me : Wait, are you sure they're not Web-UNfriendly?!? =D

1 the DELETE's about the most logical thing I got so far! :P
2 sorry Dave, your post is the only one I could directly reference to HATEOS

4 comments:

John said...

The biggest thing I like about REST is that I can look at a Web Service with my browser and understand the result myself. Sure, specifying everything with wsdl has advantages too. But since there's so much stuff out there on the web already in human-readable format, maybe our software has to be able to use that. If we can design services that are discoverable by regular web searchers during regular surfing, we might find that they end up being used more.

It's like IPv4: surely we should have abandoned that by now for something better. But there's so much of it out there, and it already works, that you just can't ignore it. You have to try to fit in and do the best you can with it.

Saager Mhatre said...

I disagree; although not the biggest, integration is perhaps one of the most painful bottlenecks to getting something out there. Integration end-points should be intentional, not accidental. If I'm going to put up a service, I'll publish a well defined API using a accepted protocol/standard that fits my model. I may even provide a web simulator for it. But I'm not sure I want to base it on another application protocol; I'm diving further down the stack. I want to leverage the Net, not the Web.

The web is, finally, only a document delivery architecture. Overloading that will only cause abstractions to leak, or result in unnatural/faulty abstractions.

Besides HTTP is a lousy protocol for application development, unless the system is inherently completely stateless. So-called RESTful services like Google translate and search work, but could be much better.

Also, I'd say the IPv4 argument goes somewhat against the grain of your argument. IPv4 (or anything at the transport layer and below) is not human-readable.

Jeremy Lightsmith said...

I think you're missing the point of REST. Once your team embraces REST, you stop having those arguments about where stuff lives.

It sounds like you're using rails. Once your team embraces REST, you'll never have to learn a completely new strategy that maps to a completely new domain (that is actually suspiciously not that different from the last 5 that you worked with) for how to name controllers and what to put in views.

In my opinion, having worked on and built many rails apps, the two most simplifying and helpful guidelines for rails architecture are REST and "fat model, skinny controller". They help stop us as developers from arguing and wasting time thinking about where stuff lives so we can spend time designing our domain layer in our models, because that's what our clients are paying us to do.

Saager Mhatre said...

I'm sorry, but I'm completely confused. I believe that REST has very little (if any) to do with implementation of your business logic. It's all about the interface.
I'll admit my first RESTful service implementation was in RoR (with Restlet clients that we messed up :P), but that has nothing to do with my rant.
My rant is around the semantics of REST as an integration interface and not about 'fat models and skinny controllers'.or services were fat models fronted by skinny controllers (avg 3 lines per method), but the interfaces of the resources themselves were preposterous. In order to avoid 'chattiness' we ended up creating vague coarse-grained resource verbs that made the client interaction look positively preposterous.
That's where I'm coming from.