RESTful 是那种咋一听很有道理,仔细思考一下又觉得然并卵的东西。在乘法云的设计中,IO Adapter 实质上就是把各种外部的 API,统一适配成 RESTful 的风格。回答了 RESTful 的收益是什么,也就回答了为什么需要搞一层 IO Adapter。

RESTful 的本质

RESTful 分为两块:

  • HATEOAS (Hypermedia as the Engine of Application State)
  • 对 operation 进行了分类

本文只讨论对 operation 分类这部分。所谓 operation-oritented 的 API,就是大家熟知的 RPC。而 resource-oriented 的 API,就是所谓的 RESTful。把 API 设计成 RESTful 的就是把 operation 分成以下4类:

  • GET - read
  • POST - create
  • PUT - update
  • DELETE - delete

约定就是 POST 之后的创建的 resource 可以通过 id GET 回来。PUT 更新了的字段,再次 GET 可以看到更新。DELETE 删掉的 resource 无法自此通过 id GET 回来。例如一篇博客文章,Article。

因为很多 operation 并不能满足上面的约定,所以就感觉无法变成 RESTful 的。比如,假设我们有一个概念叫外卖订单 Order。那么这个订单就需要支持已下单,商家接单,骑手到店,骑手开始配送,已收货等多种操作。我们不可能让 Order 支持 PUT 操作,直接允许对 status 的修改。所以对 Order 来说,只有三个操作

  • GET - loadOrder, queryOrder
  • POST - createOrder
  • DELETE - deleteOrder

对订单的更新不能用 PUT,只能用创建命令的形式(可以想象为给 order 办公室提交了一个修改申请的公文),间接进行修改。以商家接单为例,命令叫 MerchantConfirmation,对应的 operation 应该分为:

  • POST - createMerchantConfirmation
  • GET - getMerchantConfirmation
  • DELETE - deleteMerchantConfirmation

通过 RESTful 的 sub-resource 的概念,我们可以表达两个 resource 之间这种紧密的关系

POST /order/xxx/merchantConfirmation

也就是 RESTful 把多个关联的 operation 进行了分类,哪些是 GET 哪些是 POST。然后又把 resource 之间进行了远近关系的分类,紧密的 resource 变成 sub-resource。

进一步分类

沿着分类的思路。我们可以看到博客文章 Article 和外卖订单 Order 以及 MerchantConfirmation其实很不一样。我们可以把 resource 分为以下几类

  • Passive Record:完整支持 CRUD 四种操作
  • Party/Place/Thing:生命周期长,一般没有状态机,但是部分字段不支持 PUT 操作
  • Moment Interval(Business Transaction):生命周期短,一般有状态机,所有字段不支持 PUT 操作
  • Immutable Command/Event:POST 的时候是 Command,GET 的时候就变成 Event 了。

Passive Record 就是类似博客文章 Article 这样的东西。其特点是业务约束或者合同几乎没有,或者说交易发生在线下。所以线上的数据只是一份被动的记录。比如说今天的天气,这个记录没有什么可商量的余地,测量得是什么就是什么。

Party/Place/Thing 和 Moment Interval 就是带有业务约束的数据。因为业务约束的存在,所以无法保证 PUT 之后的改动,能 GET 回来。PUT 其实就是最简单的业务逻辑,写啥是啥。所以有业务约束保护的字段或者整个 resource 是无法支持 PUT 的。例如司机档案,对于一些无关紧要的字段,例如司机的兴趣爱好,随便 CRUD 都可以。但是司机的年龄,司机的驾照,这些信息和这个司机是否能在平台上接单直接相关,是绝对不允许随意 PUT 的。

Moment Interval 一般指订单这样的东西,相比司机,客户,账户这些概念,生命周期要短很多。而且一般都有强的状态机的约束。对于 Moment Interval 的修改,都需要用 POST 创建一个 command 的方法来间接修改,不能直接 PUT。我们可以把这些 command 建模成 sub-resource。

如果一个 resource 从创建,到创建完成就不再变化了。那么它就是一个 Immutable Command / Event。对于同步操作,就是 POST 的时候,直接完成处理固化成一个 Event 了。如果是异步操作,那么 POST 的时候还是 command,有一个 id。然后再次 GET 的时。候,就可以知道 command 是不是已经变成 event 了。例如食客提交一个取消订单的申请(OrderCancel),这个申请需要10分钟内得到商家的确认是同意还是拒绝,当商家给出答复之后这个命令就变成了一个已经发生的事件了。可以认为 OrderCancel 这个 resource 是由 OrderCancelCommand 和 OrderCancelEvent 两部分构成的。当创建的时候,只有 command 部分。在处理完成了之后,OrderCancel 才是一个完整的 event。

command 又可以分为两种,作为 sub-resource 的 command,和自由的 command。如果一个 command 的处理过程中会修改很多个 resource,那么就不适合分类为某个 resource 的 sub-resource 了。

event 暴露出 GET 的接口,并支持 atom 的协议,就可以替代 event bus 或者 message queue 用轮询来实现系统之间的通知的语义了。因为 Event 自身具有 immutable 的属性,所以这些 GET 接口,带上时间段就可以是永久缓存的。

RESTful 的收益

RESTful 的技术层面的收益,jim webber 等人都已经讲得非常清楚了。无非就是因为分类,使得中间的 middle-ware 可以根据类型做一些预定义的动作。另外一个额外的好处是因为 POST 的 command,需要 GET 回来。一些同步的操作,在 RESTful 之后我们会更倾向于建模成异步的,瞬时的操作会持久下来。这样会导致很多错误场景更好处理,系统也会在错误的发生的时候更健壮,考虑的边界条件会更全面。

RESTful 在编程心理学层面的收益才是更主要的。一个最显然易见的收益是通过统一 API 成为整齐一致的风格,减少了学习成本。然后通过分类,它使得 API 的用户能够很好的复用先前的知识。比如程序员都知道 POST 了之后可以 GET,所以这两个 operation 的关系通过分类就不言自明了。如果我们能把 resource 进一步分为 passive record,moment interval 等类型,那么 API 的用户又可以进一步复用已知的知识,快速把新概念套到旧的刻板印象里。噢,这个东西是个有状态机的 moment interval,那个东西是一个 immutable event。

另外一方面通过动词名化,我们引入了名词概念。再通过 sub-resource 之类的手段,让这些名词之间映射到几何空间,具有距离上的远近。从认知上来说,这种具有某种空间意义的名词,更容易留下印象,在头脑中构建出“meaning”。

所以就像所有高级编程语言写的程序,都有等价的汇编写法一样。不能说 RESTful 最终“干的事情”和 RPC 没有差别,就否定 RESTful 的价值。毕竟代码是写给人来看的。RESTful 通过分类,降低了代码的理解成本,对提高开发的效率是有收益的。

参考资料:

http://www.ansoncheunghk.info/article/web-apis-resource-oriented-architecture

https://www.thoughtworks.com/insights/blog/rest-api-design-resource-modeling

https://www.youtube.com/watch?v=aQVSzMV8DWc

restful可以转发么_RESTful 的收益是什么?相关推荐

  1. restful可以转发么_什么是RESTFUL?REST的请求方法有哪些,有什么区别?

    大家好,我是IT修真院上海分院第3期学员,一枚正直善良的java程序员,今天给大家分享一下,修真院java任务中的一个知识点:什么是RESTFUL?REST的请求方法有哪些,有什么区别? restFu ...

  2. restful可以转发么_DRF使用超链接API实现真正RESTful

    ‍很多API并不是真正的实现了RESTful,而应该叫做RPC (Remote Procedure Call 远程过程调用),Roy Fielding曾经提到了它们的区别,原文如下: I am get ...

  3. restful接口开发实例_Restful接口开发与测试—接口测试

    开发完接口,接下来我们需要对我们开发的接口进行测试.接口测试的方法比较多,使用接口工具或者Python来测试都可以,工具方面比如之前我们学习过的Postman或者Jmeter ,Python脚本测试可 ...

  4. 《21天转型微服务实战营》 学习笔记

    <21天转型微服务实战营> 学习笔记 目录 <21天转型微服务实战营> 学习笔记 1 微服务架构知识介绍 1.1 什么是微服务 1.2 为什么使用微服务 1.3 微服务面临的挑 ...

  5. gRPC学习之六:gRPC-Gateway集成swagger

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos gRPC学习系列文章链接 在CentOS7部署和设置G ...

  6. restful url 设计规范_restFul接口设计规范

    1. 域名 应该尽量将API部署在专用域名之下. https://api.example.com 如果确定API很简单,不会有进一步扩展,可以考虑放在主域名下. https://example.org ...

  7. restful url 设计规范_RESTful API接口设计规范

    网络应用程序,分为前端和后端两个部分.当前的发展趋势,就是前端设备层出不穷(手机.平板.桌面电脑.其他专用设备-).因此,必须有一种统一的机制,方便不同的前端设备与后端进行通信.这导致API构架的流行 ...

  8. java restful中文乱码_restful服务接口访问乱码 和 505错误

    标签: 用cxf 发部个rest服务,用浏览器访问和 HttpURLConnection 访问. 1. URL中有中文,浏览器访问正常,HttpURLConnection 失败. 解决: HttpUR ...

  9. restful适用于移动互联网厂商作为业务_Restful架构思想

    java作为一门后端语言,其厉害之处在于web,大家比较熟知的各种网络应用,java都能做,那么在这个移动优先的时代,如何继续发挥java的强大呢.通常是让java作为一个app的服务端,为app客户 ...

最新文章

  1. 《黑客秘笈——渗透测试实用指南(第2版)》目录—导读
  2. autopep8规范你的python代码
  3. TensorFlow HOWTO 1.1 线性回归
  4. 树堆(Treap)图文详解与实现
  5. runloop的mode作用是什么?
  6. FileOutputStream输出流
  7. ERROR: Library projects cannot set applicationId. applicationId is set to 'com.example.baiduditu' in
  8. 光刻厚胶 Thick Resist(SU-8 GM10xx,SU-8 Microchem,SPR220,NR26-25000P)
  9. 想找个这样的男朋友,要求高吗?
  10. C语言教程(七):函数
  11. SpringMVC中文件的上传和下载
  12. python之生产者消费者模型
  13. GRE新东方推荐学习方法(2010年左右)
  14. 卸载高版本的labview的vision模块和VAS采集模块装低版本
  15. 每天一个shell小知识(for)
  16. 网络字节序与地址转换函数
  17. Oracle增删改查(CRUD)
  18. ovftool工具的使用,保姆级教程。
  19. 基于video.js 的在线播放功能
  20. R语言LDA线性判别分析

热门文章

  1. 多多客DOODOOKE 1.x升级2.x指南
  2. Android 在已有工程中实现微信图片压缩
  3. Python 萌新 - 花10分钟学爬虫
  4. 从MVC到前后端分离(REST-个人也认为是目前比较流行和比较好的方式)
  5. 基于Windows下处理Java错误:编码GBK的不可映射字符的解决方案
  6. 一路走来一路歌—我和团队有个约会
  7. Class.forName()、Class.forName().newInstance() 、New 三者区别!
  8. break and continue;
  9. android进程守护 失效,保持Service不被Kill掉的方法--双Service守护 Android实现双进程守护 1...
  10. 对长度为200的有序表进行二分查找_程序员常用的查找算法(顺序、二分、插值、分块、斐波那契)...