Coupling in a RESTful Way
I knew Pete would respond. Actually we agree on far more than we disagree upon but I would like to elaborate on some points in his response. Pete writes:
As is well known, REST applications also constrain the operations that are available, whereas each and every web service ever written publishes a unique set of operations that the client must know and know how to orchestrate. In a perfect world (and I know it’s far from perfect), RESTful applications don’t even need to agree ahead of time on the resource representation, instead they negotiate which well-known media type will be exchanged via HTTP’s accept and Content-Type headers. Properly RESTful applications push all state out to the client, therefore reducing what the server needs to know about past interactions. REST has a cache constraint, as well, allowing the client or server to cache a response without the client application even being aware that a response was retrieved from cache. And, so long as transport level security is sufficient, a RESTful client does not need to know the security semantics of the service ahead of time either. Nor does it need to worry about breakage if GET, PUT, and DELETE are called over and over again; it knows these operations are idempotent. REST applications exchanging XML documents should not have to worry about the data types of the message’s elements and attributes. They shouldn’t care if elements they weren’t expecting suddenly appear in these messages either.
I'll concede that I didn't correctly interpret Pete's original statement around SOAP coupling. You're absolutely right that SOAP based services fail to offer any kind of uniformity for common operations. That said, I do believe there are a suite of problems where CRUD is insufficient, but that debate has probably addressed sufficiently.
There are some assertions though that I struggle with in the above paragraph. First, RESTful applications must agree on at least ONE well-known media type for their interaction to succeed. You can absolutely use content negotiation to state preferences from the client and allow the server to select its favorite. (For the record, I've designed SOAP interfaces that do the same, but I digress). But if there is no overlap between the client and server, the request is going to fail. Being realistic here, in most cases the client will be interested in a specific type of resource (message, video, product). And yes, I can be pretty relaxed if I'm looking for a message or video about the content type (although I doubt I'd accept a message for a video request). But as you move further into business resources (e.g. product) the number of representations will either narrow or become sufficiently diverse as to be impractical to support a broad set of representations. My point being as you move from common web resources, the degree of coupling between what the client wants and what the server can offer will increase.
I've never written a stateful web service and I'm disappointed to hear that anyone would suggest such lunacy! SOAP definitely kills caching, but SOAP's insistence on not supporting HTTP well kills all kinds of transport level optimizations. I think I stated my position on that pretty clearly in another article. I'll leave the security discussion to Gunnar who is far better equipped to talk to it than I.
I like the concept that REST operations need to be idempotent. This is a great property but must create some interesting challenges for REST developers. Idempotent updates can be particularly tricky when accurate tracking of state transitions is one of the business requirements. Providing idempotent operations is a concrete example of the point I was trying to make about system qualities. Stating whether your operation is or isn't idempotent is necessary and if you were to change in either direction, you could very well break clients that depended upon the other behavior.
Chris Stiles had an interesting comment which is implying I'm guilty of my own form of magic:
When people start talking on this vein several things are unclear:
- It’s unclear what the client will be actually expected to do with such an SLA.
- It’s unclear what form such specifications and how they will be flexible enough to express every conceivable form of contract/SLA .. in particular ..
- It seems that this problem calls for a mixture of type inference plus formal reasoning applied over large scale systems and minus a revolution in computing it’s unclear how any of this will be achieved.
I was definitely less than clear on my point. And I whole heartedly agree that expecting to find a formalized language for specifying these kinds of things that will then allow the client to augment it's behavior is highly unlikely. But you do need to state these up front, most likely in your documentation (you do document your public interactions, right?) My main point, previously made poorly, is public Internet interfaces will be used in ways that nobody can predict. If you aren't clear about what performance you're agreeing to, what availability you support, or how many transactions you'll accept, somebody will assume that whatever they empirically measure is the contract. And they'll build a client that depends upon it. State it. They may still do it but then they are relying upon an unsupported aspect of your contract.
I'd like to state my position again in the whole SOA vs REST debate. I'm neither pro or con either. They're both tools. They both have strengths and weaknesses. I respond to content that I feel offers opportunities for further discussion and elaboration. This isn't about winning a debate for either technology, it's about trying to illuminate what I feel are issues so they can get addressed. The goal is to make both better.
Technorati Tags: architecture, engineering, http, java, programming, protocol, rest, scalability, services, soa, software, to_read, toread, web
Cool. We're narrowing the window of dependencies a client has on a particular service. I fully admit that the content negotiation aspect of web services is highly idealized (I hinted at as much in my post) and that in the real world we will frequently need to introduce resource specific, non-stanard message types. And this will introduce a tighter coupling than desired. But, again, it's a matter of degree. RESTafarians may need to relax this constraint in practice, but at least we can still leverage the others.
Question for you: I don't understand this statement: "Idempotent updates can be particularly tricky when accurate tracking of state transitions is one of the business requirements." Can you elaborate?
As for the following sentence: "Stating whether your operation is or isn't idempotent is necessary and if you were to change in either direction, you could very well break clients that depended upon the other behavior." Actually, this option doesn't exist. The HTTP spec is very clear: GET is safe and idempotent, PUT and DELETE are idempotent, POST is neither. A client should not assume otherwise.
Posted by:Pete Lacey | Tuesday, December 19, 2006 at 06:53 PM
Idempotent updates in general are problematic. Tracking the actual transitions add to the problem though. Here is the scenario to consider:
Client 1 does GET at T1 on revision 1
Client 1 does PUT at T2, fails to detect success, now at rev 2
Client 2 does GET at T3 on rev 2
Client 2 does PUT at T4, now rev 3
Client 1 retries PUT at T5 for rev 1 to rev 2
It isn't enough to simply track that Client 1's update is on an older revision and therefore superseded. You need to insure that the state transition log has captured this update. Had the first attempt by client 1 failed above, you now have a conflict to resolve at T5.
Safe idempotent updates are tricky in general if you need to move beyond the last-in-wins semantic across the whole resource. (I try to avoid moving beyond that if possible!)
Posted by:Dan Pritchett | Tuesday, December 19, 2006 at 07:18 PM
http://www.w3.org/1999/04/Editing/
Posted by:Joe | Tuesday, December 19, 2006 at 07:27 PM
Yes.
Posted by:Dan Pritchett | Tuesday, December 19, 2006 at 07:36 PM
The mysterious "user" mentioned in the W3C spec is showing signs of possessing omniscient inference capability.
Posted by:vadim | Tuesday, December 19, 2006 at 08:23 PM
Isn't it ironic that much of the Web 2.0 businesses depend on the GET method being non-idempotent? Otherwise, PPC won't generate any revenue.
Posted by:Don Park | Tuesday, December 19, 2006 at 10:23 PM
The position that every interface REST/WS or otherwise will have to be accompanied by a certain amount of documentation to remove ambiguity is not one I would argue with. I wouldn't even argue with the notion that some of this documentation will be in machine readable form.
The problem is that there are people - out on the various standards lists - who fully believe that it is possible and desirable to have WS-* standards that would enable contract and flow to be described completely in a machine readable format.
Posted by:Chris Stiles | Thursday, December 21, 2006 at 07:01 AM
The thing is, once you come up with a format with well-understood and unambiguous, it's not that hard to make it machine-readable.
To me, the problem with WS-* description languages is not that they are readable by machines, it's that they are unreadable by humans.
Posted by:vadim | Thursday, December 21, 2006 at 08:46 AM
I'd like to state my position again in the whole SOA vs REST debate.
Not sure if this is what you intended. Missing P in SOAP?
IMO - SOA can be implemented SOAPy or RESTful.
Posted by:Just-a-speck | Saturday, December 23, 2006 at 12:54 AM
The thing is, once you come up with a format with well-understood and unambiguous
For real systems, and for the sorts of things (contracts etc) described this is never realistic. Either the description is so complex that it exceeds our ability to reduce it to a simple specification or it's so complex that it's ambiguities cannot be detected before time.
There's a reason for 'rough consensus and running code' - or 'interoperability testing' in a more formal world.
Posted by:Chris Stiles | Saturday, December 23, 2006 at 01:00 PM