|
大约在十年前,围绕基于REST和SOAP的系统曾开展了一系列的讨论。有人撰文分析了两类技术的各自利弊所在,而另有人思考了其中哪类技术更为适用,或是都适用。随着Web服务趋向于从基于SOAP转移到REST和HTTP,关注此问题的争论和讨论大都偃旗息鼓了。目前,大多数SOAP从业者已采用REST(或普通的HTTP)作为分布式系统的基础。然而,近期Pakal De Bonchamp在Medium上撰文“REST是新的SOAP”,将使用REST比喻为一种“精神类疾病测试”。
这篇文章的篇幅很长,内容详尽。复杂性是文中关注的一个关键问题。在作者Pakal看来,对于提供一个简单的API,使用RPC机制可在“数小时”内完成,但如果使用REST,则可能需要更长的时间。为什么会这样?作者给出了一种解释:
(REST)并没有给出更多的标准,也没有给出更准确的规范,仅是给出了一种模棱两可的“RESTful哲学”,趋向于陷入无休止的形而上辩论之中,并采用了大量丑陋的解决方法。
REST方法并不能直接映射为CRUD操作。我们该如何确定是否不应重用已有的资源而是需要创建新的资源实例,并且何时可以开始创建?在Pakal看来,HTTP错误代码提供的信息十分有限,而且无法表达更丰富的错误情况。他继续列出了更多的问题,最终给出结论:
你需要在重新造车轮上花费数个小时,甚至没有量身定做的适用车轮。你只能使用一个残缺脆弱的车轮,而且理解这样的车轮还需要阅读需要大量的文件,很有可能在不知深浅的情况下违反了它的使用规范。
Pakal在文中深入讨论了部分HTTP动词的细节,其中包括PUT,以及很少为人关注的PATCH的DELETE:
你想使用PUT实现资源的更新?那好,但是在部分高高在上的规范中规定了,数据输入必须与由GET接收的数据表示保持一致。那么你应该如何处理由GET返回的大量只读参数(例如创建时间、最后更新时间、服务器生成的令牌等等)?如果你简单忽略了这些参数,这是否会违反PUT的原则?无论如何,你应该考虑这些参数。但是如果参数与服务器端的值并不匹配,是否应期望得到一个“HTTP 409冲突”(强制发出一个GET...)?如果对这些参数随机赋值,是否应寄希望于服务器会忽略它们(隐藏错误,乐在其中)?如果随便选定一个参数,显然REST对只读属性是毫无头绪的,并且这个问题并不会很快得到修正。同时,GET会返回之前由POST或PUT发送的密码(甚至是信用卡号),这是很危险的。如果一定要处理这样的只写参数,那么我只能祝你好运了。噢,我还忘了提及,PUT会带来的一些危险的竞争条件。虽然多位客户端只想各自更新一些不同的域,但可能会互相覆盖对方的更改。
文中对REST架构理念、错误处理及其它许多方面做了详细的评估,结果差强人意。对于那些REST支持者和不愿相信REST不足之处的人来说,这篇文章值得一读。Pakal最后总结如下:
近乎透明的RPC,这才是99%的人真正需要的。尽管现有的RPC协议不够完善,但是完全够用。大众对Web和HTTP最小共同处的偏执喜好,大多导致了在时间和一些灰色地带上的巨大浪费。REST承诺简单性,但却交付了复杂性;承诺稳健性,却提供了脆弱性;承诺互操作性,却实现为异构性。REST将步SOAP的后尘。
对这篇文章得到了大量的评论。显而易见,部分人同意Pakal的看法,但是绝大多数人持不同观点,并指出了Pakal的论点中存在许多缺陷。例如,Filippos Vasilakis评论到:
或许你应该看一下Roy的论文(译者注:指Roy Thomas Fielding,他是REST架构的创立者,也是HTTP协议的主要编写人。在他个人网页上提供了博士论文全文)。你所攻击的,正是一些对REST的常见误解。正如Roy在论文中指出的,REST可能并不适合所有的情况,但是非常适合于客户端无法控制的情况。所以,如果你知道任何有其它任何一个模型也是自描述性的、可演化的,请告诉我们。REST具备上述所有特性,可与我们无法控制或不能控制的设备、客户端、硬件进行对话。这类似于在Apple Store中的移动应用需要10天才能部署新更改。如果你对应用的更新没有被Apple公司拒绝,你甚至不能访问或更新传感器设备等。类似情况下,我们可以使用REST,乃至最近推出的、依然有很多限制和问题的GraphQL。但如果你想出了另一个能解决可演化性问题的模型,请告诉我们。当然,RPC不算在内。
另一个评论来自于Vlad Ko:
哎哟,我刚刚读了些什么呀!你是在抱怨浪费了时间去架构适用的API吗?我认为这正是你的责任所在,并且作为一名开发者,目标就是要确保提供适用的API。在光天化日之下,抱怨每一个与REST相关或“无关”的问题,这有意义吗?太幼稚了~每种语言、协议、规范和概念都存在自身的问题和缺陷,诸如语法不合逻辑、虚拟机缓慢、缺乏类型支持、过于严格、过于松散、过于实用、缺乏足够的OOP,等等。希望你能进入软件工程的世界看看。
Christopher Patti评论道:
这是一篇优秀的文章。内容颇具冲击力,提供了大量有支撑的事实,给出了合理而详尽的方式去阐明道理。但是,有一个因素在文中并未论及,就是工具。如果正如你在文章中所说,人们放弃了现在是或曾经是逻辑纯粹典范的SOAP,这是因为一旦人们并非使用Java或者.NET做工作,这时工具真的是非常糟糕。有人告诉我,工具已经改进了。但是如果人们感到痛苦,那么他们就会采用新的工具来应对这种痛苦。我认为,你的论点是想说明我们可能选择了一条不幸的道路,并应该继续前进,为什么要这样做?你引用了其它一些更现代的协议,但是我很好奇的是,你究竟能举出哪些可直接替代SOAP或REST的具体例子。
原文不仅引发了大量直接评论,也在各大社交媒体平台掀起了轩然大波。最终,WeWork的平台工程师Phil Sturgeon以“对REST将步SOAP后尘的回应”为题目撰写了一篇文章。显然有很多人希望他能驳斥原文中的观点。
整篇文章充斥着对REST和HTTP的一些常见误解。尽管我的事业就是通过教育使人们摆脱各种混淆之处,但这些误解依然影响很深。显然,这是由于我的声音不够响亮,写得不够好,或是做得不到位。这是读者可能会在我的写作中看到的沮丧感,但并非针对原文作者。
和Pakal最初给出的文章一样,Phil的回应同样是长篇大论。Phil详细回应了Pakal指出的REST问题。例如,对于Pakal提到建造“残缺脆弱的车轮”,Phil这样回应道:
好吧,这是令人沮丧的。REST API往往为人嘲笑,因为支持者解释说人们不需要依赖于文档。REST API当然不需要文档,但是我用最近几个月的时间,为我们的API生成文档,因为它们都是RPC API。当一个API表示自身的状态、使用超媒体声明其可供性并提供了一个合约时,你可以选择去生成可读的文档,但这只是针对那些将REST API作为RPC API看待的人…… REST API的确需要更少的文档,除非你和为数不少的人一样,只是构建了一个未规范的RPC去冒充REST。
Pakal还探讨了PUT等HTTP动词中存在的风险。“听起来,这应该是由于不了解PUT的目的,进而产生的一种挫折感"。Phil的剖析和回应内容很长。实际上,即使没有阅读Pakal的原文,Phil的回应也值得一读。总而言之,文中的观点是,Pakal对REST抱怨的绝大部分(即使不是全部的话)是由于他的误解所致。Phil总结道:
我知道REST十分复杂。太多的人误以为自己理解了这个问题。一旦他们遇到了不了解的情况,就会给出错误的评判。世界各地的人们都在构建REST风格的API,这些API基本上只是“RPC+HTTP动词+一些漂亮的URL”。这看起来并不是很有帮助,所以他们大书特书,解释为什么这样做不是很有用……
事实可能的确如此。但Phil和Pakal的争鸣似乎还在继续,因为我们看到Phil又进一步更新了讨论情况。
我依然在与作者进行着富有成效的对话,帮助他了解REST的工作机制。我想各位可能也会对此感兴趣。
欢迎各位有兴趣的读者围观,了解讨论的进展情况。
程序猿的技术大观园:www.javathinker.net
|
|