架构
架构使用组件而非图

使用组件而非图

Gato GraphQL 不使用图来表示数据模型,而是使用组件。

这并非出乎意料的做法。GraphQL 项目在 Thinking in Graphs 一文中指出(重点为引用者所加):

图是对许多现实世界现象进行建模的强大工具,因为它类似于我们对底层过程的自然思维模型和语言描述。使用 GraphQL,您通过定义 schema 来将业务领域建模为图。在 schema 中,您定义不同类型的节点以及它们之间的连接/关联方式。在客户端,这创建了类似于面向对象编程的模式:引用其他类型的类型。在服务器端,由于 GraphQL 只定义接口,您可以自由地将其与任何后端(新的或旧的!)一起使用

从这个定义中,我们可以得出以下结论:

即使响应具有图的形状,这也并不意味着在服务器端处理数据时,数据实际上是以图的形式表示的。图只是一种_思维模型_,而非实际的实现

这是个好消息,因为处理图(或树)并非易事。而组件则简单得多,且能提供所有相同的优势。

通过组件简化数据模型

在服务器端使用组件来表示数据结构,在简洁性方面是最优的,因为它允许将数据的不同模型整合为单一结构。与其使用如下流程:

构建 Query 以供组件使用(客户端) => 以图/树形式处理数据(服务器) => 将数据提供给组件(客户端)

...我们的流程将变为:

组件(客户端) => 组件(服务器) => 组件(客户端)

这之所以可行,是因为 GraphQL 请求可以被视为具有「组件层级」数据结构,其中每个对象类型代表一个组件,而从一个对象类型到另一个对象类型的每个关联字段则代表一个包裹另一个组件的组件。

让我们用一个示例来直观地了解组件与 GraphQL Query 之间的关系。假设我们想要构建如下「精选导演」小部件:

精选导演小部件

使用 Vue 或 React(或任何其他基于组件的库),我们首先会识别出各个组件。在本例中,我们有外层组件 <FeaturedDirector>(红色),它包裹了组件 <Film>(蓝色),而 <Film> 本身又包裹了组件 <Actor>(绿色):

识别小部件中的组件

伪代码如下:

<!-- Component: <FeaturedDirector> -->
<div>
  Country: {country}
  {foreach films as film}
    <Film film={film} />
  {/foreach}
</div>
 
<!-- Component: <Film> -->
<div>
  Title: {title}
  Pic: {thumbnail}
  {foreach actors as actor}
    <Actor actor={actor} />
  {/foreach}
</div>
 
<!-- Component: <Actor> -->
<div>
  Name: {name}
  Photo: {avatar}
</div>

接下来,我们识别每个组件所需的数据。<FeaturedDirector> 需要 nameavatarcountry<Film> 需要 thumbnailtitle<Actor> 需要 nameavatar

识别每个组件的数据属性

然后我们构建 GraphQL Query 来获取所需数据:

query {
  featuredDirector {
    name
    country
    avatar
    films {
      title
      thumbnail
      actors {
        name
        avatar
      }
    }
  }
}

可以看出,上述组件层级与这个 GraphQL Query 之间存在直接对应关系。