Recently InfoQ did a good summary of the debates around the apparent (to some) limitations of REST when it comes to creating good Web services. At issue is that REST APIs seem to expose "CRUDy" services that fly in the face of years of good services design, particularly when they are just read/write interfaces instead of the richer, full REST architecture (more on what this is later.) The discussion was spurred by Arnon Rotem-Gal-Oz's assertion recently that CRUD is bad for REST, which in my opinion is close but not quite right.
In my view there appears to be two primary ways that REST are used today. One is via the aforementioned CRUD approach (where CRUD = Create, Read, Update, Delete) and HTTP's verbs (which in the same order as CRUD are POST, GET, PUT, DELETE) are used to manipulate a data resource on a Web server. This is the most basic, most common way REST is used by application designers (sometime even using these to replicate traditional RPC) and is the foundational request/response model in REST services. Unfortunately, it's also probably the least interesting or powerful way to apply the full REST architectural style.
For one thing, using only CRUD to manipulate data treats resources as loose, unintelligent bags of bits, seems too fine grained, and generally feels like client/server in a cheap disguise. Sure, it works extremely well with the protocol that runs the Web, HTTP, but no architect would consider this story so far good enough reason by itself to bend an entire application design around it. Things get much more interesting, however, when URIs start getting added to the mix. This happens in one of two ways and, depending on how URIs are applied, it's the key to the whole REST hypertext approach (aka HATEOAS, or "hypermedia as the engine of application state") which has worked so well on the Web for content. And now, with REST, we're doing it with data.
Data as Hypertext: Deeply Linked URIs and URIs for State Transitions
First of all, like the Web itself, REST works better when the data itself links to URIs of other resources that contain a more complete representation of a given piece of data (a line item summary might link to the full line item resource, for example). Deep linking, and not maintaining local copies of a representation is essential to prevent a variety of issues including data duplication and out-of-date copies.
Second, the very essence of REST is to make the states of an application explicit and addressable by URIs. The current state of the application state machine is represented by the URI that the client just operated on and the state representation that was returned. The client can change state simply by operating on the URI of the state it wants to move into, making that the new current state. A given state's full representation includes the links (arcs in the URI graph) to the other valid states that that can be reached from the present state. So in the visual below, we show a simple but complete interaction model that includes a single valid state transition. In short, as even Roy Fielding himself recently emphasized last year, REST APIs must be hypertext driven.

Click To Enlarge
The scenario above shows a complete and I hope canonical (albeit simple) interaction model that exhibits the full RESTful properties. The individual numbered steps of this scenario are described below:
Step 1: To use a well-designed REST API, only a single well-known URI needs to be published by the creator and referred to by the client. From this top level resource, all the resources and state transitions for the entire API and all its services can be found. A REST API is self-descriptive and therefore self-contained, with only minimal "out-of-band" documentation required. A simple HTTP GET at this URI will retrieve the API entry point.
Step 2: The API is examined and a service known as FooService is found, along with the URI for the entry point to the FooService API.
Step 3: The resource list for FooService is retrieved via GET. The URI came from the top-level API description examined in the previous step. In this example, a list of fooitems is retrieved, including possible state transitions.
Step 4: There is only one state transition, "reverse". This operation is chosen to be used in this scenario.
Step 5: A PUT (which means the resource will be modified) is issued to the URI described by the original resource. A back-end component (business logic) then reverses the name element of the resource (changing the state of the resource). A copy of the modified resource is also returned by the operation, making the operation efficient as well.
Step 6: Although a copy of the resource was returned from the state transition, the change is durable but we do another GET, this time just on the resource to see what the current state is.
Step 7: The state of the resource is examined and found to be changed by the state transition operation.
Lessons learned from the CRUD vs. Hypermedia debate
So, I think one of the biggest problems with REST is that there is no canonical description for how to use it. This is also one of its core strengths. There are many ways to apply REST to the problem at hand, and if all you need is CRUD, you are still doing basic REST and meeting your needs. No single description could do justice to the power and flexibility inherent in the model and I agree strongly with Sam Ruby that "REST isn’t an all or nothing proposition. One can get significant value from partial adoption."
But this discussion does highlight some very specific lessons learned that many REST practitioners don't often follow but are important to consider carefully in order to build services that are resilient, adaptable, and maintainable over the long term. Many of the benefits of REST aren't felt until later when you want to fix or change things. That you can do so easily is a testament to the potency of architecture of the Web, if only we can understand it clearly enough.
Here are my takeaways on what most REST adopters can and should do to get the most from their use of this increasingly popular architectural style:
- Describe your REST API via a single, well-known, top-level resource at a permanent, public URI. This resource contains descriptions and URIs of all the services (by type) that are maintained by the REST API. This provides maximum flexibility for changes down the road since well-written client code will process the changes as normal operation and not require specific alteration for many kinds of modifications to the API.
- Use business logic behind the server CRUD, return HTTP errors as appropriate. This one isn't as well known as it should be but REST services do not have to be dumb repositories of resources. They can do as much validation or processing as required for all POST, PUT operations. Don't accept data blindly from clients and return HTTP errors that make sense and describe the problem. Does this violate the self-describing aspect of REST interfaces? Not necessarily, the server imposes the valid state transition on the client and this is just another means of doing so.
- Never hard-wire URIs into the client, always assume the resource will provide the current URI to related data as well as valid state transitions. Good REST interfaces will be easy to maintain for the server, but clients can take shortcuts, either to improve performance or to simply coding. Don't do this, just dereference URIs every time and you'll pick up and use modifications to the interface largely automatically and with no code changes.
- CRUD isn't the only way to change a REST resource, invoking a state transition's URI can modify data implicitly. This is where REST can become very elegant and provide a self-describing interface and state model for changing data. Designing state models aren't what Web developers are particularly familiar with but it's a potent programming model that encourages good discipline and works for most types of applications. You can use CRUD where state transitions just don't make sense.
- Versioning is best done outside of URIs. Version all day long but don't hardcode it into the URIs themselves. This can easily be done with content negotiation. You can also read Paul Sadauskas great explanation of how to do this this well.
- The art of describing state transitions is still very much an art, study the latest conventions. There seems to be little consensus on how state transition URIs should be documented. Does one use the href tag or the uri tag? How does the resource convey exactly what the transition does in terms of altering state. This and other questions are all relatively unanswered still, though they are fairly obvious to those that examine a given REST resource. There is more consensus, for example, on how to pass parameters into state transitions or operations such as searches and queries. This is where URL Templates have made some headway and it's important to study them.
I've frequently described REST as a foundational element of Web-Oriented Architecture for both enterprise and Web applications and open data in particular. It's been thrilling to see REST become so popular in recent years, even if we have a long way to go yet to reach a wide understanding of what it is and how to use it. I hope these ideas are helpful and I'd love to hear your additions below.