GraphQL Schema 设计中的常见问题及解决方案

前言

GraphQL 作为一种 API 开发语言,逐渐被越来越多的公司、开发者所使用。其中,GraphQL 的 Schema 设计是 GraphQL 应用的核心。

在 GraphQL 应用开发的实践中,我们发现了一些常见的问题,例如定义 Schema 时出现的繁琐代码,Schema 的可读性差等等问题。本文将讨论这些常见问题,并提供解决方案。

问题一:重复的字段

当 Schema 需要多次引用同一个字段时,会产生大量重复的代码。

例如,我们定义一个查询所有书籍的 Query:

type Query {
  books: [Book!]!
}

如果我们需要对这个 Query 添加分页功能,我们可以添加一个 Paging 类型和一个新的 Query:

type Paging {
  limit: Int!
  offset: Int!
}

type Query {
  books(paging: Paging): [Book!]!
}

现在,我们想要添加一些过滤的功能,例如按照书名过滤(这其实也是我们之前已经定义过的 Book 类型的一个字段),我们需要继续修改 Query:

input FilterInput {
  name: String
  // 其他字段省略
}

type Query {
  books(paging: Paging, filter: FilterInput): [Book!]!
}

如此一来,我们就需要不断地手动添加新的参数,这会导致代码的繁琐性和可读性下降。那么,有什么解决方案吗?

解决方案

一般地,我们可以使用 Input 类型来解决这个问题。

input PagingInput {
  limit: Int!
  offset: Int!
}

input FilterInput {
  name: String
  // 其他字段省略
}

type Query {
  books(paging: PagingInput, filter: FilterInput): [Book!]!
}

我们定义了两个 Input 类型,其中 PagingInput 和 FilterInput 分别对应了 Query 的两个参数。这样一来,我们就可以将重复的字段提取到 Input 类型里面,大大减少了代码的冗余。

问题二:Schema 的可读性差

当 Schema 越来越复杂时,其可读性往往会下降。

例如,下面这个 Schema:

type Query {
  books: [Book!]!
  findBooks(query: String): [Book!]!
}

type Mutation {
  createBook(input: CreateBookInput!): Book!
  updateBook(id: ID!, input: UpdateBookInput!): Book!
  deleteBook(id: ID!): Boolean
}

type Book {
  id: ID!
  name: String!
  author: Author!
}

type Author {
  id: ID!
  name: String!
}

很难一下子看出其中的关系和逻辑。

解决方案

我们可以通过常见的 Schema 组织方式来解决这个问题。

使用 Interface 和 Union

使用 Interface 和 Union 类型可以帮助我们更好地抽象出 Schema 的共性,并减少冗余代码。

例如,我们可以将 Book 和 Author 的共性抽象成一个 Person 接口:

interface Person {
  id: ID!
  name: String!
}

type Author implements Person {
  id: ID!
  name: String!
}

type Book {
  id: ID!
  name: String!
  author: Person!
}

这样我们就可以将 Book 中的 author 字段的类型定义成 Person,从而减少一些代码的冗余。

使用 Fragment

使用 Fragment 可以帮助我们更清晰地查看 Schema 中的结构。

例如,我们可以定义一个 BookFragment:

fragment BookFragment on Book {
  id
  name
  author {
    id
    name
  }
}

然后在 Query 中使用 BookFragment:

type Query {
  books: [Book!]!
  findBooks(query: String): [Book!]!
  findBook(id: ID!): Book!
}

type Mutation {
  createBook(input: CreateBookInput!): Book!
  updateBook(id: ID!, input: UpdateBookInput!): Book!
  deleteBook(id: ID!): Boolean
}

type Book {
  ...BookFragment
}

type Author {
  ...AuthorFragment
}

这样一来,我们就可以很方便地调查和查看 Schema 中的结构,并且 Schema 的可读性也提高了。

总结

本文讨论了 GraphQL Schema 设计中的两个常见问题,对应地提供了两种解决方案。当 Schema 越来越复杂时,我们应该采取相应的措施来提高可读性和可维护性。

最后,我们提醒读者在进行 Schema 设计时,应该注重设计思想和代码质量。这样一来,我们可以写出更好的 GraphQL 应用,为用户带来更好的体验。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65a8f2abadd4f0e0ff237561


纠错反馈