译者:杰微刊兼职翻译汪建
作者:Howard Dierking
最近我花了一些时间和我的团队从API的角度来聊了REST的话题,同样也讨论了如何利用诸如违反了REST的最重要原则的Swagger技术去创建API。正如我在讨论中说的,那就是REST风格不是用来描述API。REST描述了整个系统的架构特性,用于描述此该系统包含了所有哪些不同组成的部分。它尝试基于组件对系统提出系统级别的要求,甚至是对系统不起作用的一层。
“我们对于REST风格最大的帮倒忙的行为之一就是我们在REST后面添加了API字眼!”
目前我见过几个不同公司的处理场景,这些公司在最纯粹的定义上将一个服务搭建成REST风格,客户端通过各种方式的使用让系统变得非REST风格。更糟的是,这使得人们更难在跟高层次上阐明REST的价值,因为“REST风格”的API在易用性和长期稳定性方面与RPC这方面的性能并没有明显的差异。事实上,在某些情况下,某些性能会被认为差得多,比如可用性方面。
对于客户端来说,在REST风格和非REST风格的系统之间有两个明显的方式:URL结构和文档结构。
正如我敢肯定的是你听说过广告令人厌倦,避免由客户端构造URL而是由服务端提供连接,这是REST风格的超媒体的核心,这使得服务器真正拥有它的所有资源的名称和位置。从而使其能够独立于它的客户端进行演变。但是,这仅仅当客户端使用服务端提供的连接时才有效,但更多地我比较愿意承认,在客户端真实的编程时他们会忽略服务端连接,而是用基于URL(多次硬编码)的连接在之前的响应体中加上各种数据。Swagger工具(甚至GraphQL)鼓励这种使用它们的URI膜拜和占位符的模式。
客户端和服务器端之间更加隐藏的耦合是涉及到如何领会每个请求和响应的有效负载,在REST理想世界中,客户端和服务器都绑定到一个标准的IANA注册的上下文类型中,而且不会尝试去理解任何超过以上范围的事情,然而这不是我们生活的世界,它无疑不是我们希望生活的世界。业务系统通过他们的性质、域特性等自然结果,即使是在相同的域中的每个系统彼此之间都有稍微不同的方言。无论是对还是错,这些差异是分化多次而作为竞争优势。此外,业务(和支持他的数据视图)可以根据各种因素在响应中快速改变。你可以多频繁地支持标准媒体型的变化?得知它是以年计的你可能不会感到惊讶。
所以,如果一个客户端和服务器不能依赖于绑定到一个标准的内容类型去互相理解他们之间互相传输的数据的话,那他们稳定性还可以依赖什么呢?恩,就像法定货币一样,没有什么。
好吧,这无可否认具有一点戏剧性。但问题是系统的稳定性确实在服务器和客户端之间没有双关语义的用于理解数据的协议。这些规则必须在某处记录起来然后在客户端和服务器进行编码。规则可以用标记或结构化描述语言来记录,并且他们可以直接在代码中、在模式文档中、在混合情况下进行编码,从模式文档中生成代码。对于所有的这些策略、工具、技术,提醒着存在一个“数据合同”(从我的WCF日子中借用此概念)代表客户端和服务端之间互相作用从而使得系统很稳定。任何数据合同的改变必然导致服务契约的改变。在更复杂的联合服务中,其实还是有很多客户端绑定的小数据合同。鉴于这一事实,WSDL和Swagger合并文档模式到API程序描述文档可能是正确的,将模式作为参数的类型(尽管我还是不同意这些大体上的策略)。
当谈及REST时,人们如何构建客户端真的是IMO的核心问题。在实践中,REST风格系统的前提是具有通用的客户端,对于我们正在做的系统这样做可能是不切实际的,市面上为什么只有这么少数量的浏览器的原因是,构建浏览器是很难的。然而,这是因为标准内容类型的复杂性,比如HTML和协议、HTTP和DNS。它可以尽力基于潜在用户而被调整的。就像对于业务系统,甚至是一个很庞大的系统,它更加难以调整类似的。尤其是当需要创建(并获得成功,更广泛的行业支持)一个类似于HTML的标准内容类型时。
所以,当我们讨论API时,也许现在是时候要理智真诚地放弃使用“REST”术语了。这将可以让我们停止围绕着他们是否是真正的REST风格上越包越多,同时使我们能不觉得有必要拿出像“务实REST”条款。或许我们应该着眼于建设可用的Web API。对我们用户来说,可用性是重点。