自2007年以来,我一直在使用ActiveResource,并建立和维护了一个多服务分布式架构,使用ARes从Rails v1.2到v4.0的过程中。在我看来,ARes在其当前形式下作为一个公共库是基本有缺陷的,但它包含了很多好的想法,可以在个人系统中使用。我曾经发表演讲,介绍我们公司如何迁移离开ARes。
人们不喜欢使用 ARes 的一个重要原因是由于维护不良或实现细节上的分歧。例如,你的同事提到的错误信息处理就属于这一类。此外,随着时间的推移,由于不明智的一次性改进或错误修复,甚至是 Rails 内部更改(例如去年
YAML-pocalypse 发生时),你会发现一些意外破坏了 ARes 系统。但所有这些问题都可以通过更好的维护和更好的愿景来改善,重要的是将这些问题与
根本 问题分开。
我所相信的,并且 Yehuda 在他上面的评论中所暗示的,是 ARes 失败是因为 REST API 没有一般具体的语义。即使利用最好的 Rails 约定,HTTP API 语义也是脆弱的。
与ActiveRecord不同的是,它生成SQL:一种用于选择数据行的明确定义的声明性语言。 SQL基于关系模型,根据不同子句给出了查询含义的数学定义。 这种数学基础是使得Arel可以在Ruby中创建可组合的SQL DSL的原因。在SQL数据库中,任何语法正确的查询都可以被执行(即使它太慢而无法实际使用),因为引擎被设计为正式解析和映射SQL语句以证明正确地实现操作和提取底层数据。因此,当您在其上构建像ActiveRecord这样的ORM时,您拥有底层系统的非常强大的保证。如果您生成有效的SQL,则引擎保证它将工作;如果您生成无效的SQL,则引擎将返回错误。即使使用了标准化的SQL,值得注意的是,每个数据库都有一个单独的ActiveRecord适配器,以确保正确性和正确映射到ActiveRecord功能。每个适配器都使用底层驱动程序来保证向正在运行的数据库正确实现线协议。所有这些代码都有相当多的规范和维护,所有这些都使今天的ActiveRecord具有良好的优雅和可靠性。
现在考虑一个HTTP API及其后端。它可以是任何数据库技术,也可能没有!它很可能是内部编写的,并仅提供业务功能所需的内容。与数据库不同,数据库模式中包含了有关通用查询操作的所有必要信息,而HTTP API完全与底层存储机制或业务逻辑解耦。即使API提供了如何使用查询参数的标准,也没有自我记录哪些过滤器或排序选项可用的定义。甚至检查参数的有效性也不能保证,因为API通常会吞下或忽略无效的参数。
话虽如此,ARes非常方便,但它建立在流沙之上。它使用的想法和约定很方便,但它们缺乏一个统一的愿景和稳定性来保证可靠性。个人认为,使用自己的约定和可靠规范构建类似于ARes的服务实现并不是不合理的。
就构建一个基础设施来支持像 ARes 这样的东西而言,Yehuda Katz 和 Steve Klabnik 的出色的 JSON:API 规范是一个伟大的社区项目,将为这样一个基础设施提供一个非常重要的构建块。然而值得注意的是,它仍然无法与特定的数据库驱动程序相比,具有语义保证和可推导功能。我怀疑一个真正好的利用 JSON-API 的类 ARes 库将会在很大程度上不同于今天的形式,以更好地拥抱与 RDBMS 相比隐含的灰色领域。
编辑:JSON:API 经过两年的激烈辩论和来自不同社区的反馈,刚刚发布了 1.0 版本。我估计这个规范所做的工作量比 ActiveResource 做的多几个数量级。虽然它与 ActiveResource 不同的抽象层次,但 JSON:API 追求的目标类似,即提供标准语义,使 API 更易于生成和消费。查看一些 implementations 可以很好地了解 JSON:API 可以提供多少杠杆效应。