GraphQL 是不是消除了数据传输对象?
Posted
技术标签:
【中文标题】GraphQL 是不是消除了数据传输对象?【英文标题】:Does GraphQL obviate Data Transfer Objects?GraphQL 是否消除了数据传输对象? 【发布时间】:2018-09-06 04:23:29 【问题描述】:据我了解,Data Transfer Objects (DTO) 通常是小型、扁平、无行为、可序列化的对象,其主要优点是易于跨网络传输。
GraphQL 有以下几个方面:
鼓励服务rich object graphs,这(无论如何在我的脑海中)与 DTO 的“扁平化”部分相矛盾, 让客户choose exactly the data they want,解决“小”部分, 返回JSON-esque objects,用于处理“无行为”和“可序列化”部分GraphQL 和 DTO 模式是否相互排斥?
这就是导致这个问题的原因:我们设想了一个带有网关的微服务架构。我正在设计一个 API 以适应该架构,该架构将服务(除其他外)geometries。在许多(可能是大多数)情况下,几何图形对客户端应用程序没有用处,但它们在其他应用程序中至关重要,因此必须提供服务。然而,它们是序列化的,几何图形可能很大,因此让客户可以选择拒绝它们可以节省大量带宽。我见过的处理几何图形的 RESTful API 通过在查询字符串中提供 "returnGeometry" parameter 来做到这一点。我从未对这种方法感到完全满意,我最初设想为一组相当深的相关/嵌套返回对象提供服务,其中许多客户会选择拒绝。所有这些都让我考虑使用 GraphQL 接口。随着设计的进展,我开始考虑扁平化输出(完全或部分),这导致我考虑 DTO 模式。所以现在我想知道是否最好将所有内容扁平化为 DTO 并跳过 GraphQL(我想是支持 REST 吗?)。我考虑过使用 GraphQL 服务的 DTO 的中间立场,让客户选择他们想要的属性,但我想知道这是否不恰当地混合了模式和技术。
【问题讨论】:
【参考方案1】:我认为区分 GraphQL 的 2 个典型用例和结合前两个的隐藏的第 3 个用例是值得的。
然而,在所有这 3 个中,GraphType 的本质是选择性地决定要从域实体中公开哪些字段。听起来很熟悉?它应该,这就是 DTO。 GraphQL 与否,例如,您不想在用户表上公开“密码”字段,因此您需要以一种或另一种方式向客户隐藏它。
这是因为 GraphQL 不对您的持久层做出任何假设,并为您提供了根据您认为合适的方式处理输入类型/查询的工具。
1. GraphQL 端点直接暴露给客户端(例如网络、移动):
在这个用例中,您可以使用任何 GraphQL 客户端直接与您的 graphql
端点通信。这里的 DTO 是实际的 GraphType 对象,其结构取决于您添加到公开的 GraphType 中的字段。
在内部,您将使用字段解析器将您的 DTO 转换为您的域实体,然后使用您的存储库来持久化它。
DTO 转换发生在内部GraphType 的字段解析器。
GraphQL --> DTO --> Domain Entity --> Data Store
2. 向客户端公开的 REST 端点,它在内部使用 GraphQL 端点:
在此用例中,您的 Web 和移动客户端通过 REST 使用传统 DTO。然而,控制器连接到一个内部公开的 GraphQL 端点 - 与用例 #1 不同 - 其 GraphTypes 是您的域实体的精确映射,包括密码字段!
DTO 转换发生在控制器调用端点之前。
DTO --> Domain Entity --> GraphQL --> Data Store
3.结合1和2
这是一个用例,当您将架构从一个转移到另一个时,您又不想破坏客户消费者的东西,因此您将两个选项都保持打开状态并最终停用其中一个。
希望这会有所帮助!
【讨论】:
我的问题专门针对您的场景 #1,其中客户端直接与 GraphQL 端点对话。它询问在这种情况下是否可以接受公开一系列平面类并使用 GraphQL 允许客户端选择他们想要检索的类(及其属性)。我认为您的回答表明,是的,没关系。我读对了吗? 是的,你没看错!这完全没问题,符合良好的域建模(具有 DTO 或等效项)以上是关于GraphQL 是不是消除了数据传输对象?的主要内容,如果未能解决你的问题,请参考以下文章
我是不是错误地使用了 GraphQL?我不知道它是如何向我发回数据的
GraphQL 忽略了一些(但不是全部)任意分配的 markdown frontmatter 数据
.NET 遇上 GraphQL使用 Hot Chocolate 构建 GraphQL 服务