将您的 Data 和 Application API 分离:更进一步

Carson Gross

TLDR: 如果您将 API 分离为 Data API 和 Application API,如这里所倡导, 您应该考虑将 Application API 从 JSON 更改为 Hypermedia (HTML) & 使用像 htmx 这样的 hypermedia-oriented 库,以收获 hypermedia 模型的好处 (简单性、可靠性、灵活性 等)

问题

最近,Max Chernyak 写了一篇题为 Don’t Build A General Purpose API To Power Your Own Front End 的文章。他的 TLDR 是这样的:

YAGNI,除非您在一家拥有联邦前端或 GraphQL 的大型公司工作。

他随后讨论了通用 API 和您的应用 API 的不同需求。他将以下内容列为通用 API 的需求:

  1. 如何预测并启用所有可能的流程
  2. 如何避免 N+1 请求用于awkward 流程
  3. 如何测试每个可能请求的功能性、性能和安全性
  4. 如何在不破坏现有流程的情况下更改 API
  5. 如何在内部和社区需求之间优先级排序 API 更改
  6. 如何文档化一切,以便所有各方都能完成工作

而这些作为应用 API 的需求:

  1. 如何收集渲染页面所需的所有数据
  2. 如何优化对多个端点的请求
  3. 如何避免以非预期方式使用 API 数据字段
  4. 如何权衡新功能的好处与新 API 请求的成本

我将这种需求的不匹配称为 Data/App API 阻抗不匹配 问题。

Max 的建议是将 API 分割成两个“半部分”:一个通用 API 和一个应用 API:

我建议您停止将前端视为某种通用 API 客户端,而是开始将其视为您应用的一半。

想象一下,如果您可以直接发送整个“页面”价值的 JSON。创建一个 /page/a 端点,并在那里渲染整个 /page/a 的 JSON。 为每个页面都这样做。不要强迫您的前端开发者发送一堆单个请求来渲染一个复杂的页面。 停止用人为的限制来烦扰他们。保持一致。

正确认识错误之处

我完全同意 Max 在这里的问题描述。

我特别要强调的是,通用 API 需要保持稳定,而应用 API 必须快速变化以满足应用需求。

Jean-Jacques Dubray 在 这篇文章 中描述了 API 设计师的以下悲惨状况:

如今我工作中最糟糕的部分是为前端开发者设计 API。谈话不可避免地是这样:

开发者 – 所以,这个屏幕有数据元素 x、y、z……您能创建一个 API,响应格式为 {x: , y:, z: } 吗?

我 – 好的

这是 Max 所注意到的张力的完美概括,API 工程师想要设计通用、稳定的 API,但却要屈从于快速变化的 UI 的突发奇想,该 UI 具有复杂的数据需求,这些需求往往最好在 服务器端 解决。

正如 Max 指出的:

您可以让“页面 a”保持简单,只做它需要做的事。您可以彻底测试“页面 a”以查找 bug、安全性和性能。您甚至可以用一个大的 SQL 查询为“页面 a”获取一切。

错误认识正确之处

因此,我再次完全同意 Max 存在 Data/App API 阻抗不匹配问题,我赞扬他建议而不是转向像 GraphQL 这样的解决方案,而是将 API 分割成两个。

然而,还有一个 下一步 要采取:

一旦您将应用 API 与通用数据 API 分离,您就不再受公共数据 API 约束的限制,并且可以自由重新考虑该应用 API 的 整个形式。我们可以随心所欲地处理它,所以让我们在思考上更宽广一些。

请注意,应用 API 的核心问题是快速变化和特定于页面(或资源)的调优。事实证明,我们有一种非常好的技术来处理 确切 的这个问题:Hypermedia

Hypermedia 通过 HATEOAS 使 API churn 成为问题要小得多。当您更改 hypermedia API 的形状时,没关系: API 简单地反映在服务器返回的 HTML 中。您可以添加和修改端点,而且,看吧(在一阶近似下),您的客户端(即浏览器)不需要更新。

浏览器只是看到新的 HTML,而 驱动它们的用户会适当地对新功能做出反应

因此,虽然我觉得 Max 走在正确的轨道上,但我认为他 没有走得够远:一旦您在精神上跳跃到通过将两者分离成独立关注点来解决 Data/APP API 阻抗不匹配问题,那么再往前走一点路,就可以重新发现 hypermedia 的优势。

您可能会反对说:“哦,但是 hypermedia 应用的可使用性不是很高,我们不想回到 web 1.0。”

这是一个完全合理的反对意见,但人们一直在研究这个问题,现在有许多库可用,这些库在 hypermedia 模型 内部 解决了 HTML 的可用性问题。

我最喜欢的两个是 unpoly 和,当然,我自己的 htmx

结论

如果您切换到 hypermedia 应用 API(这实际上只是“使用 HTML,就像您以前那样”),那么您将获得 REST-ful web 模型的所有好处(简单性、可靠性 等)以及成熟 web 框架中服务器端渲染的好处 (缓存、SQL 调优 等)

而且,通过选择像 htmx 这样的 hypermedia 导向前端技术,您可以在该模型中创建 优秀用户体验

旧的一切又新了,但这一次,有一点更好。

</>