Arnon Rotem-Gal-Oz starts his new post "CRUD is bad for REST" by stating that:
On the surface, it seems like a very good fit (both technically and architecturally), however scratch that surface, and you’d see that it isn’t a good fit for either.
Today’s most common implementation of the REST architectural style is based on HTTP and consequently on HTTP verbs namely POST, GET, PUT and DELETE. Common implementers map these verbs into CRUD terms - Create, Read, Update and Delete. A typical mapping is 1 to 1:
- GET is typically mapped to CRUD Read although GET provides a few features beyond an out-of-the-box SELECT (Read) mapping.
- DELETE is typically mapped to CRUD Delete
- PUT is typically mapped to CRUD Update, but with several caveats:
- PUT requires a complete replacement for the resource while Update can be partial.
- PUT can be used to Create a resource (when the URI is set by the client)
- POST is typically mapped to CRUD Create but it supports only the creation of a child resource. POST also can be used to provide partial update to a resource.
In Arnon ’s opinion:
the HTTP verbs are more document oriented than database oriented - while you can update, delete and create new resources the way you do that is not exactly CRUD in the database sense of the word - at least when it comes to using the HTTP verbs.
But the biggest reason why CRUD is not an appropriate paradigm for REST is an architectural one. In the heart of REST is the implementation of the protocol state machine using hypermedia. Arnon quotes Tim Ewald:
... Here's what I came to understand. Every communication protocol has a state machine. For some protocols they are very simple, for others they are more complex. When you implement a protocol via RPC, you build methods that modify the state of the communication. That state is maintained as a black box at the endpoint. Because the protocol state is hidden, it is easy to get things wrong. For instance, you might call Process before calling Init. People have been looking for ways to avoid these problems by annotating interface type information for a long time, but I'm not aware of any mainstream solutions. The fact that the state of the protocol is encapsulated behind method invocations that modify that state in non-obvious ways also makes versioning interesting.
The essence of REST is to make the states of the protocol explicit and addressable by URIs. The current state of the protocol state machine is represented by the URI you just operated on and the state representation you retrieved. You change state by operating on the URI of the state you're moving to, making that your new state. A state's representation includes the links (arcs in the graph) to the other states that you can move to from the current state. This is exactly how browser based apps work, and there is no reason that your app's protocol can't work that way too. (The ATOM Publishing protocol is the canonical example, though its easy to think that its about entities, not a state machine.)
Following John Evdemon’s article, explaining why CRUDy services is an SOA anti pattern, Arnon explains the disadvantages of CRUD REST:
- It circumvents the whole idea about "Services" - there's no business logic.
- It is exposing internal database structure or data rather than a thought-out contract.
- It encourages bypassing real services and going straight to their data.
- It creates a blob service (the data source).
- It encourages minuscule demi-serices (the multiple "interfaces" of said blob) that disregard few of the fallacies of distributed computing.
- It is just client-server in sheep's clothing.
Arnon ends his post by reemphasizing that just adopting standards like HTTP, XML, JSON (although might be useful) does not constitute REST - adopting the REST architecture does.
This post is an important remainder that REST, similar to SOA, is not a set of standards and popular APIs, but rather an architectural paradigm, which needs to be understood and followed.