CRUD不适合REST吗?

2009 年 8 月 03 日

Arnon Rotem-Gal-Oz 在他的新博文"CRUD 不适合 REST"中这样开篇:

表面上看起来它们很相配(无论从技术上还是架构上),然而,一旦深入了解,你就会发现它们并不相配。

今天,REST 架构风格的常见实现是基于 HTTP 协议及其相应动作(如 POST,GET, PUT 和 DELET)的。而且,这些动作经常会被实现者映射为 CRUD 术语——Create,Read,Update 和 Delete。典型的做法是 1 对 1 映射。

  • GET 通常被映射为 CRUD 中的 Read,只是 GET 还提供了超越开箱即用(Out-of-the-box)的 SELECT(即 Read)映射的一些特征。
  • DELETE 通常被映射为 CRUD 中的 Delete
  • PUT 通常映射为 CRUD 中的 Update,只不过增加了一些限制:
    • PUT 替换的对象是整个资源,而 Update 可以替换一部分。
    • PUT 可以用于创建一个资源(当客户端设定 RUI 时)
  • POST 通常被映射为 CRUD 中的 Create,但它仅支持创建子资源,可是 POST 支持对资源的部分更新。

Arnon 认为:

HTTP 动作更加面向文档而不是数据库,至少在谈到 HTTP 动作时,执行 Update,Delete 和 Create 新资源采用的做法和 CRUD 在数据库的世界里的做法是不完全一样的。

然而,CRUD 不适合于 REST 的最大原因是架构上的,REST 的核心是使用超媒体实现的协议状态机。Arnon 引用 Tim Ewald 的话

……这是我所理解的。每一种交互协议都有一个状态机,有些很简单,有些则比较复杂。当你通过 RPC 来实现协议时,你是在创建用于修改交互状态的方法。从交互端点看来,状态是由一个黑盒子维护的。由于协议状态是隐藏的,所以很容易出错。比如,你很有可能在初始化之前就调用某个流程。很长一段时间里,人们一直通过为接口的类型信息下注解的方式来寻找避免这类问题出现的方法,但是我从没有看到任何主流的解决方法。事实上,协议的状态隐藏在方法调用的背后,在方法调用的过程中隐式地修改状态,这个事实更增了版本控制的趣味。

REST 的精髓是通过 URI 来显式描述协议的状态。协议状态机的当前状态是由最近一次操作的 URI 以及该操作获取到的状态描述决定的。若要修改状态,那么就对 URI 进行相应的目标状态的操作,使资源呈现期待的新状态。状态描述包括指向其他状态的链接(状态图中的弧线),通过这些链接可以从当前状态移动到目标状态。基于浏览器的应用就是这么工作的,而且你的应用程序协议没有理由不能那样工作。(ATOM 发布协议是一个经典的状态机例子,尽管它被经常认为是关于实体的,而不是状态机的)

接着 John Evdemon&rsquo 的文章中所阐述的为什么 CRUD 服务是 SOA 的反模式,Arnon 描述了 CRUD REST 的缺点:

  • 限制了服务的整体概念——没有业务逻辑。
  • 暴露了内部的数据库结构,或者数据接口,而不是仔细考虑后的接口。
  • 鼓励直通服务和数据的做法。
  • 建立的是块(Blob)服务(数据源)
  • 鼓励细小的多重服务(为块服务定义多重接口),而忽略了分布式计算的若干谬误。
  • 仅仅是“批着羊皮”的 C-S 结构。

Arnon 在博文结尾的时候再次强调,仅仅采用诸如 HTTP,XML,JASON 等标准(尽管他们很有用)还不能构成 REST,而只有采用了 REST 架构才算真正的 REST。

这篇博文的重要性在于它提醒到:REST 和 SOA 类似,它不是一组标准和流行的 API,而是一种架构模型,这才是需要去理解和遵循的。

查看英文原文: Is CRUD Bad for REST?

2009 年 8 月 03 日 21:163376
用户头像

发布了 184 篇内容, 共 64.7 次阅读, 收获喜欢 1 次。

关注

评论

发布
暂无评论
发现更多内容

架构师训练营第三周学习总结

张明森

从拼多多突破阿里和京东两大巨头绞杀,市值破千亿美金来看职业价值链

非著名程序员

程序员 程序人生 职业规划 程序员成长 职业成长

游戏夜读 | RPG的美式和日式

game1night

啥是CPU缓存?又如何提高缓存命中率呢?

八两

Java操作Excel竟如此简单

生命在于折腾

Java EasyExcel

SpringIOC 是依赖倒置吗?

yupi

在项目中随手把haseMap改成了currenHaseMap差点被公司给开除了

java金融

Java 后端 BigDecimal金额 Arrays.asList

由一次管理后台定时推送功能引发的对 RabbitMQ 延迟队列的思考 (二)

LSJ

Java RabbitMQ 延迟队列 优先级队列

区块链系列教程之:比特币的钱包与交易

程序那些事

比特币 区块链 智能合约 钱包 交易

终于有人把 java代理 讲清楚了,万字详解!

java金融

Java jdk 后端 动态代理 cglib

在 React 仓库中的那些 package

teabyii

源码 前端 React

架构师训练营 - 第2周学习总结

红了哟

效率思维模式与Zombie Scrum

Worktile

敏捷开发

[安利] 可能会让你爱上书写的工具组合!

猴哥一一 cium

Typora markdown markdown编辑器 玩转写作平台

Kafka面试题:基础27问,必须都会的呀!

Java小咖秀

大数据 kafka 分布式 队列 延时消息

【Golang runtime学习笔记-启动过程分析】

卓丁

golang 初始化 runtime 汇编 go汇编

策略模式解析

七哥爱编程

设计模式 策略模式

golang-pprof实战笔记

卓丁

golang pprof 性能分析

Git 基础知识学习

LeoBing

把主机放在家里

centos Homework

依赖倒置-好莱坞原则

yupi

如何做好职场印象管理?

石云升

职场 印象管理 职场形象

[架构师训练营] 2 依赖倒置

悬浮

软件设计原则

yupi

三流程序员大晚上不睡觉,竟然在做这件事

Janenesome

写作平台 碎碎念

一款跨平台免费的开源 SQL 编辑器和数据库管理器!

JackTian

数据库 sql GitHub 开源项目 实用工具

ArrayList哪种循环效率更好你真的清楚吗

java金融

Java 后端 ArrayList 循环效率 方式

优化工程师逻辑视角下的微信“拍一拍”功能

Earth_Polarbear

人工智能 微信 系统工程 优化逻辑

实现一个redis命令--nonzerodecr

老胡爱分享

redis 源码分析 源码阅读

2020最新阿里Java高级面试题(首发,50道附答案)

互联网架构师小马

Java世界的“烂”包管理

阿喜伯

maven Git Submodule

CRUD不适合REST吗?-InfoQ