CRUD is bad for REST

[For Arnon Rotem-Gal-Oz’s Article:http://dobbscodetalk.com/index.php?option=com_myblog&show=CRUD-is-bad-for-REST.html&Itemid=29]In
one of my previous posts (Rest: good, bad and ugly), I made a passing
comment, about how I think using CRUD in RESTful service  is a bad
practice. I received a few comments / questions asking why do I say that
– so what’s wrong with CRUD and REST?

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.

REST
over HTTP is the most common (almost only) implementation of the REST
architectural style - to the point REST over HTTP is synonymous with
REST. I would say most of the people who think of REST in CRUD terms,
think about mapping of the HTTP verbs.

CRUD
which stands for Create, Read, Update and Delete, are the four basic
database operations. Some of the  HTTP verbs, namely POST, GET, PUT and
DELETE (there are others like OPTIONS or HEAD) seem to have a 1-1
mapping to CRUD. As I said earlier they don’t. The table below briefly
contrast HTTP verbs and CRUD

 

Verb CRUDdy Candidate Actually
GET SELECT (Read) Get
a representation of a resource. While it is very similar to SELECT it
also has a few features beyond an out-of-the-box SELECT e.g. by using
If-Modified-Since (and similar modifiers) you might get an empty reply.
Delete Delete Maps well
PUT Update Put looks like an update but it isn’t since:
1. You have to provide a complete replacement for the resource (again similar to update but not quite)
2. You can use PUT to create a resource (when the URI is set by the client)
POST Insert It
can be used to create a   but it should be a child/subordinate  one.
Furthermore, it can be used to provide partial update to a resource
(i.e. not resulting in a new URI)
OPTIONS ? Get the available ways to continue considering the current state or the resource
HEAD ? Get the headers or metadata about the resource (which you would otherwise GET)

The way I see it,  the HTTP verbs are more document oriented than database oriented (which is why document databases like CouchDB
are seamlessly RESTful). In any event, what I tried to show here is
that 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.

However,
the main reason CRUD is wrong for REST is an architectural one. One of
the base characteristics(*) of REST is using hypermedia to externalize
the statemachine of the protocol (a.k.a. HATEOS– Hypertext as the engine
of state). The URI to URI transition is what makes the protocol tick
(the transaction implementation by Alexandros  discussed in the previous post shows a good example of following this principle).

Tim Ewald explains this  nicely (in a post from 2007…) :


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
addressableg 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.)

If
you are busy with inserting and updating (CRUDing) resources you are
not, in fact, thinking about protocols or externalizing a State machine
and, in my opinion, miss the whole point about REST.

CRUD services leads and promoted to the database as a service kind of thinking (e.g. ADO.NET data services) which as I explained in another post last year is a bad idea since:

  1. It circumvents the whole idea about "Services" - there's no business logic.
  2. It is exposing internal database structure or data rather than a thought-out contract.
  3. It encourages bypassing real services and going straight to their data.
  4. It creates a blob service (the data source).
  5. It
    encourages minuscule demi-serices (the multiple "interfaces" of said
    blob) that disregard few of the fallacies of distributed computing.
  6. It is just client-server in sheep's clothing.

The
main theme of this and the previous post is that if we try to drag REST
to the same old, same old stuff we always did we wouldn’t really get
that many benefits. In fact, the “old” ways of doing that stuff are
probably more suitable for the job anyway since they have been in use
for a while now. and they are “tried and tested”  (“You can’t win an
argument with an idiot, he’ll just drag you down to his level and beat
you with experience” …). REST is just  a different paradigm that RPC,
ACID transactions and CRUD.

 

*
I know I sound like a broken record on that but our industry has a
history diluting terms to a point they almost stop being useful (SOA
comes to mind..). The way I see it you can have 3 levels on your way to
REST over HTTP:

  • You can be using HTTP and XML/JSON – this is level 1 or “Using standards”.
  • You
    can be using the HTTP verbs properly and/or applying document oriented
    communications – this is level 2 or “Rest-like” interface
  • You can conform to all REST constraints and be at level 3 or “RESTful”.

All levels can be useful and bring you merit but only the 3rd is REST

作者:蒋金楠
微信公众账号:大内老A
微博:www.weibo.com/artech
如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号蒋金楠的自媒体将会停用)。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

原文链接

时间: 2024-09-15 09:22:37

CRUD is bad for REST的相关文章

PHP 构建语义Web CRUD 操作

创建.读.更新和删除(Create/Read/Update/Delete,CRUD)操作是最基本的数据库操作,但是它们也是最重要的操作.CRUD 操作通常是使用关系数据库系统中的结构化查询语言(Structured Query Language,SQL)完成的.随着 Web 变得更加具有面向数据特性,因此需要从基于 SQL 的 CRUD 操作转移到基于语义 Web 的 CRUD 操作.了解如何使用 PHP 通过基于语义的 Web 执行 CRUD 操作. 常用缩写词 API - 应用程序编程接口(

自动生成数据对象代码和CRUD操作的C#代码生成器

对象|数据 笔者近期在Vs2005平台和SqlServer2005平台之上研发了一个C#代码生成器,支持数据库表和C#数据对象的直接映射,以及CRUD操作代码的自动生成,用户只需要实现IDAL接口即可,该工具能够显著提高开发速度,让开发人员从繁重的数据库表对象封装编码中解脱出来(工具下载地址:http://itabby.com/index-5.asp),现特将核心处理代码进行发表,仅供参考: ///数据对象提取部分数据库类型和C#对象类型之间的转换过程private string Convert

使用Dojo和Grails快速实现数据的增删改查(CRUD)

选择 Grails 和 Dojo 的原因 随着 web 的广泛应用,web application 的开发项 目越来越多,而大部分的 web 开发归根结底都是对数据库的增删改查.对于一张数据库表的 增删改查,采用基于 MVC(模型 - 视图 - 控制器)设计模式的开发往往需要 Domain class . Controller.4 个增删改查的页面.form 输入数据的校验等.这样就免不了大量类似功 能的复制粘贴修改. 如果你想从重复劳动中解放出来,Grails 是一个很好的选择. 使用 Gra

MyBATIS使用CRUD

MyEclipse不提供自动生成,这里提供mybatis文件包和开发文档 http://download.csdn.net/detail/u010026901/7489319 自己建立配置文件, <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http

Rails开发细节(二)CRUD

Create & Save 创建 & 保存 order = Order.new order.name = "virusswb" order.email = "asdf@exmaple.com" order.save 调用save方法之后就可以保存到数据库了. 还可以用block来创建并保存. Order.new do |order| order.name = "virusswb" order.email = "asdf@

Lucene 3.6.2入门(2) 针对索引文件的CRUD

package com.jadyer.lucene; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.

Ruby on rails开发从头来(windows)(二十)-测试model(CRUD)

上篇随笔简单了解了rails的测试和测试用数据的使用,这次来看看怎样对一个model进行添删查改的测试. 1.还是使用上次写的products_test.rb,修改test_turth方法的名字为test_create,并且使其内容为: def test_create assert_kind_of Product, @product assert_equal 1, @product.id assert_equal "Pragmatic Version Control", @produc

PHP构建语义Web CRUD操作

创建.读.更新和删除(Create/Read/Update/Delete,CRUD)操作是最基本的数据库操作,但是它们也是最重要的操作.CRUD操作通常是使用关系数据库系统中的结构化查询语言(Structured Query Language,SQL)完成的.随着Web 变得更加具有面向数据特性,因此需要从基于SQL的CRUD操作转移到基于语义 Web的CRUD操作.了解如何使用PHP 通过基于语义的Web 执行 CRUD操作. 常用缩写词 API - 应用程序编程接口(Application

LINQ那些事儿(2)- 简单对象的CRUD操作和Association的级联操作

从(1)我们看到,当生成entity class定义时,entity class或xml mapping文件中都已经完整的包含了entity和关系数据库的映射信息了,LINQ2SQL会根据这些信息来把CRUD操作转化为SQL提交给数据库,并且把数据库的返回DataTable封装成我们想要的对象. 所谓简单对象,就是数据表定义中没有Foreign-key的entity class,在操作这类对象时不会涉及级联的操作. 简单对象的CRUD操作,可参考MSDN:http://msdn.microsof

ADO.NET与ORM的比较(4) EntityFramework实现CRUD

说明:个人感觉在Java领域大型开发都离不了ORM的身影,所谓的SSH就是 Spring+Struts+Hibernate,除了在学习基础知识的时候被告知可以使用JDBC操 作数据库之外,大量的书籍中都是讲述使用Hibernate这个ORM工具来操作数据. 在.NET中操作数据库的方式有多种,除了最直接的方式就是使用ADO.NET之外, 还可以使用NHibernate这个Hibernate在.NET中的实现ORM,如果你对第三方的 ORM 持怀疑态度,你还可以使用来自微软的实现.根正苗红的Lin