如何设计 GraphQL schema 以最大化 API 的可维护性

阅读时长 8 分钟读完

GraphQL 作为一种新式的 API 技术,其优势在于客户端可以根据自己的需要精确地获取所需数据,而不是像传统 REST API 那样获取大量冗余数据。在使用 GraphQL 构建 API 时,一个重要的因素是如何设计 schema,它决定了数据的结构和查询方式,并直接影响 API 的可维护性。本文将介绍如何设计 GraphQL schema 以最大化 API 的可维护性。

1. 分清实体和关系

在设计 schema 时,首先要明确的是数据实体和它们之间的关系。实体是指系统中的对象,例如用户、订单、商品等等。关系是实体之间的联系,例如用户可以下单,订单包含商品等。

在 GraphQL 中可以通过类型来定义实体和关系,类型包括对象类型、输入类型、接口类型和枚举类型。对象类型用于表示实体,输入类型用于输入参数,接口类型用于表示多种类型的公共接口,枚举类型用于枚举常量。设定明确的类型有利于开发人员在查询和更新数据时准确地识别类型和字段。

例如,在一个电商网站中,可以定义 User 类型表示用户,Order 类型表示订单,Product 类型表示商品,而 User 和 Order 之间的关系可以通过 Order 上的 user 字段定义。另外,Product 和 Category 之间一般是多对一的关系,可以通过 product 上的 category 字段定义。

2. 采用模块化设计

模块化设计是提高代码可维护性的一种有效方式,因为它可以将代码分成小模块,每个模块负责不同的功能。在 GraphQL schema 中也可以采用模块化设计,将不同实体和关系分成不同的模块,每个模块包含其自身的类型、查询、变更等内容。

GraphQL 已经具备了一定的模块化能力,通过 Directive 可以动态地修改 schema,使其更加灵活。例如 @include 和 @skip 可以根据条件决定是否包含某个字段,@deprecated 可以标记某个字段已经弃用。这些 Directive 可以让我们更好地控制 schema 的行为,进而提高 API 的可维护性。

例如,在电商网站中可以将 User、Order 和 Product 分别定义为不同的模块,每个模块包含自己的类型、查询和变更,并通过 Directive 控制字段的访问权限和错误处理等。

3. 使用接口和联合类型

GraphQL 可以支持多种类型,其中接口和联合类型是两种非常有用的类型。接口用于表示多个类型的公共接口,而联合类型则用于表示多个类型的联合。这两种类型可以帮助我们将一些公共的属性定义在一个接口中,同时也可以让多个不同类型共享某些公共的字段。

在实际应用中,我们可以将不同实体的公共属性抽象成一个接口类型,然后让各个实体类型都继承自该接口类型,这样就可以在查询时动态的确定具体的类型,并返回所需的数据。

例如,在电商网站中,可以将 User 和 Order 分别定义为一个对象类型,然后定义一个 Userable 接口类型,里面包含了 User 和 Order 共同的属性和方法。再将 User 和 Order 都继承自 Userable,这样查询时就可以根据需求确定查询的某个实体,从而返回该实体的属性和方法,类似于多态的概念。

4. 使用 DataLoader 和缓存

DataLoader 是一个用于解决数据加载问题的 JavaScript 库,它可以按照需求批量地加载数据,并自动批量请求。在 GraphQL schema 中使用 DataLoader 可以有效地提高查询效率、减少网络请求次数以及减轻数据库负担。

另外,缓存也是提高 API 性能和可维护性的重要方式之一,因为使用缓存可以减少网络请求次数,并在数据被缓存时加快响应速度。在 GraphQL 中使用缓存可以通过一些现成的库和框架,例如 redis、apollo-server 等。

例如,在电商网站中使用 DataLoader 和缓存可以有效地提高 API 性能。可以将用户、订单和商品的数据存储在一个数据库中,并通过 DataLoader 和缓存加快查询速度,并减少数据库查询次数。

结论

上面介绍了如何设计 GraphQL schema 以最大化 API 的可维护性。在真实应用中,schema 的设计需要根据具体业务需求而定,但以上原则是在不同场景中都适用的。

这里附上一个基于 GraphQL 和 Node.js 的示例代码,该代码演示了如何快速构建一个简单的电商平台,欢迎参考!

-- -------------------- ---- -------
---- ------- -
  --- ----
  ----- -------
  ------------ -------
  ------ ------
  --------- ---------
-

---- -------- -
  --- ----
  ----- -------
  --------- -----------
-

--------- -------- -
  --- ----
  ----- -------
  ------ -------
-

---- ---- ---------- -------- -
  --- ----
  ----- -------
  ------ -------
  ------- ---------
-

---- ----- -
  --- ----
  ----- -----
  --------- -----------
-

---- ----- -
  --- ----
  ----------- ------ -------
  ------------ ------ --------
-

---- -------- -
  ------------------- ----- ----------- --------- ------
-
-- -------------------- ---- -------
----- - ------------- --- - - -------------------------
----- ---------- - ----------------------
----- ----- - -----------------

----- ------ - ---------------------

----- ------------- - --- -----------
  ----- ----- -- -
    ----- -------- - ----- ---------------------- -- ------------------
    ------ -------------------- -- ---------------------
  --
  - ------ ----- -
--

----- -------------- - --- -----------
  ----- ----- -- -
    ----- ---------- - ----- ---------------------- -- -------------------
    ------ ----------------------- -- ----------------------
  --
  - ------ ----- -
--

----- --------- - -
  ------ -
    --- -------- ----- -------- -- -
      -- ----- ---------
    --
    -------- ----- -------- - -- -- -------- -- -
      ----- ------- - ----- -----------------------
      ------ --------
    --
    --------- ----- -------- - -- -- -------- -- -
      ----- -------- - ----- ------------------------
      ------ ---------
    -
  --
  --------- -
    ------------ ----- -------- - ------- ---------- -- -------- -- -
      -- ----- ----
    -
  --
  ----- -
    ------- ----- -------- ----- - ----------- -- -- -
      -- ----- -------
    -
  --
  --------- -
    --------- ----- -------- ----- - ----------- -- -- -
      -- ----- -------
    -
  --
  -------- -
    --------- ----- -------- ----- - ----------- -- -- -
      -- ----- -------
    -
  -
--

----- -------- - ----
  -------------------------------------- ------------------ --------
--

----- ------ - --- --------------
  ---------
  ----------
  -------- -- --- -- -- -- --- ---
  ------------ -- -- ----
---

----------------------- --- -- -- -
  --------------- ------ ----- -- ---------
---

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/675338728bd460d3ad9bdafa

纠错
反馈