GraphQL Schema 设计:构建可演进的 Schema

Posted FENews

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GraphQL Schema 设计:构建可演进的 Schema相关的知识,希望对你有一定的参考价值。

译者:May Zhang

这是 Marc-Andre Giroux 的客座文章,他目前正在 GitHub 的生态系统 API 团队工作。他一直在编写和思考 GraphQL 持续进化和模式设计。如果您需要一些 GraphQL 的帮助,可以通过 marc@mgiroux.me 与他联系。

虽然 GraphQL 允许我们不断改进我们的 schema,例如使用 GraphQL 内置的废弃字段的方式,但我们不应该轻易地废弃 schema 中的字段。最后,在最好的情况下,我们废弃一个字段仍然需要我们的集成商做一些工作来适配这个改动,而最坏的情况是对于那些没有做出改动的人来说这是一个破坏性的改动。

虽然可以通过更好的工具和文档(例如我们在 GitHub 上 build 的文档)以更简单的方式来进行这些更改,但是我们必须记住,如果我们想要一个让集成商信任并且稳定的 API,那么使用自带的废弃字段的方式绝对是最后的手段。

好消息是,有一些方法可以构建我们的 GraphQL schema,以避免将来发生严重的重大变化。在构建 API 时,我们必须记住,需求会发生变化,我们要为这种情况做好充足准备。在这篇文章中,我们将探讨在为未来设计 API 时可以提供帮助的一些事项。

1. 对象类型优先于更简单的结构

以此 CalendarEvent 类型为例,注意 timeRange 字段,它表示事件何时开始并结束。乍一看,这看起来还不错。我们有一个列表类型,它可能与我们内部匹配,以索引为 0 的数组开始,索引 1 为结尾。

现在如果我们想要添加更多与该范围相关的数据呢?例如,该时间范围是过去还是将来?在它的当前状态中,我们必须向 CalendarEvent 添加一个字段。我们将其命名为 timeRange ,好让我们的集成商知道它们是相关的。或者最糟糕的是,我们最终会废弃 timeRange 并为 timeRange 字段做出不同的设计。

GraphQL Schema 设计:构建可演进的 Schema


这里的问题是我们无法在同一个 timeRange 字段中添加这些数据,因为我们遇到了一个扁平的 DateTime 数组。如果我们用不同的方式设计 timeRange 字段会怎么样?如果我们在这里使用了一个对象类型而不是一个数组,我们最终会得到如下的结果:

这样做更好的原因主要有以下几点:

  1. 我们可以轻松地为 TimeRange 类型添加任何我们想要的额外数据。

  2. 我们已经命名了我们的字段,而不是使用数组索引,这对于集成商来说是非常有用的。

  3. 相关数据在单个类型中就能找到,而不需要通过字段名称前缀来执行此操作。

试想一下你为你的字段或参数使用的类型是否是未来不会改变的。如有疑问,请使用更复杂的结构,如 object 类型或 input 类型。

2.有疑问时,具体命名

当我们开始构建 GraphQL Schema 时,我们可以使用名称的整个命名空间。在创建一个新类型时,我们很容易使用最简单的方法来描述新实体。例如,采用 Comment 类型来描述某人在 SomeSocialMedia™ 上发布的帖子的评论。

在一段时间内,这对我们来说可能是完美的。但是,我们最终可能会引入另一种评论,而这个评论实际上和之前的是不同的。例如,这个新的评论类可能是新的应用程序反馈的表单评论。它的目的是完全不同的,它有不同的字段,但也有共同的字段。

现在我们必须将新评论命名为 FeedbackFormComment,我们坚持使用代表帖子评论的通用对象类型 Comment。试想一下,如果我们想要建立一个 Comment 接口,我们就会意识到我们有一些具有相同行为的类型,那么我们的帖子评论现在已经窃取了接口的通用名称了 

以上是关于GraphQL Schema 设计:构建可演进的 Schema的主要内容,如果未能解决你的问题,请参考以下文章

GraphQL 和 graphql-sequelize-schema-generator

程序员架构修炼之道:如何设计出可持续演进的系统架构?

graphql-code-generator 依据graphql schema自动生成客户端类型定义

graphql-java 循环类型依赖

用于可扩展项目的 graphql 代码组织

无法从模式拼接中的另一个 schema.graphql 文件中的其他 schema.graphql 文件访问共享模式