所有文章 > API设计 > REST、GraphQL 和 gRPC 的自动化风格指南
REST、GraphQL 和 gRPC 的自动化风格指南

REST、GraphQL 和 gRPC 的自动化风格指南

如果你问 100 位开发者关于分号的使用位置,你可能会得到 100 种不同的答案,或者引发一场激烈的争论。为了避免这种情况,大多数团队都会采用样式指南。样式指南不仅帮助团队保持代码风格一致,还能避免新成员因为代码风格问题而受到指责。Linter(代码检查工具)就是一个很好的辅助工具,它不仅能推荐最佳实践,还会指出技术上允许但可能带来隐患的代码。随着 API 描述的日益重要,Linter 在这方面的应用也变得越来越广泛。

例如,JavaScript 开发者常用 eslint,PHP 开发者有 PHP Code Sniffer,而 Ruby 开发者则使用 rubocop。这些 Linter 工具不仅仅检查语法是否正确,还会验证代码是否符合特定的规则集。这些规则集有时由公司内部定义,例如非常流行的 eslint-airbnb 规则集。有时,它们是由行业标准组织制定的,比如 PHP-FIG 制定的 PSR-12 标准,CodeSniffer 就有对应的 PSR-12 规则集。

说到 API 文档,大多数大公司都有自己的“样式指南”或“设计手册”。这些指南通常存放在 Google Docs、wiki 或其他文档管理系统中。

基于文本的风格指南是否很浪费时间?

这些基于文本的文档有一个明显的问题:它们通常冗长、内容简洁却枯燥,开发人员很少会花时间去仔细阅读。即使有开发人员认真通读并记住了所有内容,一旦添加新规则,这些知识也会变得部分过时。要了解最新的规则,开发人员不得不重新从头到尾再读一遍整个文档,这显然是不现实的。

在 API the Docs 上,我听到了 Salesforce 的 Kelsey Lambert 的演讲。他们的风格指南是基于 OpenAPI 描述文档的示例,要求开发人员在特定情况下参考这些文档,了解他们应该使用哪些规范。然而,Salesforce 这家巨头公司拥有 238479347 个 API,每个 API 还维护着 40 个主要版本。他们的风格指南执行方式竟然是靠开发人员的目测和记忆。真是让人无奈!

其实,这种混乱不应归咎于任何一个开发人员。API 开发者已经够忙了,而负责编写风格指南的人往往也是摸着石头过河。这种混乱其实是整个行业面临的问题。但幸运的是,已经有一些工具开始出现,能够自动化地执行这些风格指南的规则,从而帮助解决这个困境。

  • Google 的api-linter
  • Cap Collectif的graphql-doctor
  • Christian Joudrey的graphql-schema-linter

每个项目都着手做相对类似的事情,但是针对不同类型的 API。

HTTP API 的 Spectral如何使用?

Spectral 是一个 JSON/YAML 数据检查器,具有针对 OpenAPI v2/v3 和 JSON Schema 的内置规则。

在普通文档上运行默认的 OpenAPI 规则集会发现很多建议,这对不完全熟悉 OpenAPI 的开发人员很有帮助。提醒人们添加参数描述之类的小事可以帮助使文档更易于阅读,而他们可能甚至没有意识到这是可能的。

错误太多

您可以使用 Spectral 创建规则集,这些规则集可以具有自定义规则甚至自定义功能!

这些自定义规则看起来有点像这样:

规则:schema-names-pascal-case:描述:模式名称必须以 PascalCase 格式书写消息:'{{property}} 不是 PascalCase:{{error}}' 推荐:true 类型:style 给定:'$.components.schemas.~' 然后:功能:模式 functionOptions:匹配:'^[AZ][a-zA-Z0-9]$'

这个比较流行。OpenAPI 并不关心你如何将模型首字母大写,但很多代码生成器会使用模型名称来编写代码,而不一致的类名会让人不爽。

让我们更进一步:

规则:paths-kebab-case:描述:路径是否应为 kebab-case。消息:'{{property}} 不是 kebab-case:{{error}}'严重性:警告推荐:true 给定:$.paths[*]~ 然后:功能:模式 functionOptions:匹配:“^(/[a-z0-9-{}]+)+$”

此规则实际上超越了 API 描述的元数据,而是着眼于实际的 API 设计本身。这意味着“路径”(接口)必须带连字符,因此/recent-files是可以的,但/recent_files不行。

您可以开始真正发挥创造力。

规则:no-x-headers:描述:“请不要使用带有 X- 的标题”消息:“标题不能以 X- 开头,因此请为 {{property}} 找到一个新名称。更多信息:https://tools.ietf.org/html/rfc6648”推荐:true 给定:“$..parameters.[?(@.in === 'header')].name”然后:功能:模式 functionOptions:notMatch:'^(x|X)-'

我不知道为什么,但在任何给定 API 的生命周期的某个时刻,一些开发人员会建议添加 X-Foo 标头,尽管十多年来它一直导致问题。好吧,我们可以用这条规则把他们拒之门外。

如果尽早完成,这将在开发过程中塑造实际的 API。如果您先编写代码,那么好吧,您必须返回并更改一堆代码。希望您没有发布它,因为现在您需要为/recent_files /recent_files进行大量重定向。如果您使用API 设计优先工作流程,那么当您刚刚获得一些 YAML 时,您会尽早注意到这一点,并且您的 API 首先得到构建。

由于 Spectral 是一个 CLI/JS 工具,因此可以通过各种方式来执行此样式指南。

  • 在git hook中
  • 在 JS 测试套件中
  • 关于持续集成导致构建失败的错误

如果您使用Stoplight Studio,那么它就会直接嵌入到编辑器中,因此设计 API 的人可以立即正确完成所有操作。无需按 Alt-Tab 键转到 CLI 或等到 PR 完成。

红绿灯工作室里的 Spectral

我正在努力抽出时间从Heroku或PayPal获取样式指南,并将它们转换成一个巨大的示例规则集。至少,我可以从中汲取一些灵感,用于我正在整理的新规则集:OpenAPI Contrib > 样式指南。这应该是一个有趣的社区努力。

Spectral 还有一个GitHub Action,我们正在努力改进它。评论范围和建议即将推出!

GraphQL Doctor 和 Schema Linter的区别?

GraphQL 有自己的内置类型系统,其中有一些与基于 OpenAPI / JSON Schema 相同类型的关键字。

GraphQL 使一些设计决策变得更容易,比如如何处理关系。无需在嵌套/嵌入相关资源、使用复合文档内联所有内容或使用超链接链接到相关数据之间做出选择,GraphQL 会为您做出决定。尽管如此,在 GraphQL 做出的默认决策之外,仍可能出现许多不一致的情况。GraphQL 人员无法逃避 lint 的需要,但幸运的是,存在一个很棒的 linter:GraphQL Schema Linter。

GraphQl Schema Linter

也可以为此编写自定义规则,这样您就可以在 CI 中自动化您的样式指南。我看不到机器人或 GitHub Action,但它们并不难组合在一起。

GraphQL 领域中一款拥有出色机器人的架构工具是 GraphQL Doctor。它似乎希望在总体上提供更多帮助,但到目前为止,它专注于检测重大更改。与任何类型的系统一样,谨慎发展和鲁莽更改之间存在一条细线,而 GraphQL Doctor 会发现后者。

graphql doctor bot 的预览,评论 github pull request,显示发生故障的行

如果这两个工具能够合并就好了,或者 GraphQL Doctor 机器人可以支持 GraphQL Schema Linter,但就目前而言,它是一个两站式商店。

Google 的“API Linter”是什么?

Google 在 API 领域做了一些非常有趣的工作。他们是 API 领域首批不断解释“有时你需要 REST,有时你需要 RPC”的大公司之一,并且他们坚持使用适用于gRPC 和 HTTP 的通用工具。API linter 在 protobuf 表层上运行,但可以设置为与 HTTP 端点一起工作:

使用协议缓冲区时,每个 RPC 都必须使用 google.api.http 注释定义 HTTP 方法和路径:

rpc CreateBook(CreateBookRequest) 返回 (Book) { option (google.api.http) = { post: "/v1/{parent=publishers/}/books/" body: "book" }; } message CreateBookRequest { // 将出版这本书的出版商。 // 使用 HTTP/JSON 时,由于语法的原因,此字段会根据 URI 自动填充。 string parent = 1; // 要创建的书籍。 // 使用 HTTP/JSON 时,由于语法的原因,此字段会根据 HTTP 正文填充。 Book book = 2; // 用户指定的书籍 ID。 // 使用 HTTP/JSON 时,此字段会根据查询字符串参数填充,例如。这是 URI 或正文中未包含的字段的后备。 string book_id = 3; }

API Linter 的核心规则集相当令人印象深刻,它重点关注 HTTP 规范中不太清楚的尴尬部分。例如,GET 应该有一个主体吗?答案是“也许可以”,但很可能没有,这取决于你正在构建的工具,呃。求助。

谷歌决定直接回答:不。

无 HTTP 主体

他们还决定说服团队从 proto2 升级到 proto3。

原型3

有哪些可用的规则创意?

您可以使用这些东西自动化几乎任何事情,并且我一直在思考许多超越强制命名或复数化的常见用例的规则。

安全

  • 完全禁止 HTTP Basic
  • 确保每个端点都具有某种安全性(OAuth 2、API 密钥,但不能同时具有)
  • 每个响应都应该支持application/vnd.api+json (JSON:API),而不仅仅是普通的 JSON
  • 整数形式的 ID 可以让人们非常轻松地抓取你的 API,请切换到 UUID

错误

  • 你的20X回复好像有错误,你为什么讨厌你的消费者
  • 您的错误中没有 URL,别人如何才能找到有关错误的更多信息
  • 错误格式应为RFC 7807

版本控制

  • 请勿将版本号包含在 URL 中
  • 请在标题中输入版本号
  • 摒弃版本控制,拥抱变革(准备迎接挑战)

这些规则中有许多是特定于 HTTP API 的,但您明白我的意思。随着时间的推移,我将研究其中一些规则,并将它们添加到 OpenAPI Contrib 的样式指南中,如果您愿意做出贡献,我很乐意在 GitHub 上指导您完成整个过程。

总结

如果您听说过 API 治理这个术语,那么大多数人都在谈论这个术语。目前,许多试图进行治理的人都在仔细查看每个 PR 上的 API 描述,并培训人们记住他们提出的所有质量规则。

手动 API 培训是一项吃力不讨好、效率低下、永无止境的任务,它可以被编辑器、git hook、CI 管道、GitHub Action 或机器人中嵌入的 linter 所取代(或大幅简化)。

不要浪费客户的时间强迫他们尝试找出您的不一致之处。不要浪费所有 API 开发人员的时间来学习记住样式指南。不要浪费 API 管理团队的时间来手动审查 API。不要浪费每个人的时间来修复生产中的不一致之处。

原文链接:Automated Style Guides for REST, GraphQL and gRPC

#你可能也喜欢这些API文章!