【问题标题】:How bad would it be to have nested mutations?嵌套突变会有多糟糕?
【发布时间】:2017-03-03 21:10:42
【问题描述】:

我知道它会被视为一种反模式,但究竟为什么呢?

mutation {
  createUser(name: "john doe") {
    addToTeam(teamID: "123") {
      name,
      id
    },

    id
  }
}

难道不比两次 HTTP 调用更方便吗?

mutation {
  createUser(name: "john doe") {
    id, # we store the ID
  }
}

mutation {
  addToTeam(userID: id, teamID: "123") {
    name,
    id,
  }
}

【问题讨论】:

  • 为什么不在createUser() 中添加一个可选的teamID,以便在一个HTTP 请求中使用更传统的突变来完成这一切?
  • 是的,如果您想每次都将用户添加到团队中,它实际上会起作用,但如果不是这样,您是否需要在服务器上创建一个额外的突变:createUserAndAddToTeam?跨度>
  • “如果您想每次都将用户添加到团队中,它实际上会起作用”——不。可选的teamID 是可选的。对类型使用String! 意味着您可以传入null 以表明您不想将用户添加到团队中。
  • 哦,是的,我没有考虑过这个选项。

标签: graphql


【解决方案1】:

如果您在 TeamUser 之间有关系,则可以公开此 API:

创建用户,与现有团队相关

mutation {
  createUser(name: "john doe", teamId: "team-id") {
    id
    team {
      id
    }
  }
}

创建新用户和新团队

mutation {
  createUser(name: "john doe", team: {name: "New team"}) {    
    id
    team {
      id
    }
  }
}

这正是 Graphcool API 处理此问题的方式,如 this blog article 所示。您可以在the documentation 中找到另一个示例。

【讨论】:

  • 这个突变的参数如何传递给嵌套类型?返回字段team { id } 是如何解决的?我正在尝试进行类似的突变,但 GraphQL 说它需要一个根参数:stackoverflow.com/questions/50211978/…
【解决方案2】:

这是一个反模式有两个原因:

首先,这里有两个原子操作,每个都可能涉及一些额外的与身份验证、验证相关的逻辑,并产生不同的错误。因此,将它们混合在一起可能会导致一些额外的复杂性。

例如,假设一个团队只能有 10 人,并且已达到最大值。撰写操作是否应该完全失败?我们应该只添加用户而不将其添加到团队中吗?响应会是什么样子?

第二,以这种方式合并两个操作可能会暴露应用程序逻辑。人们可能很想使用这种突变来执行“当 X 发生时,Y 也应该发生”。例如,向发票添加新行时,应更新总数。这应该真的发生在一个突变中,addLineToInvoice,并将逻辑驻留在服务器上。

在某种程度上,API 的命令部分最好以流程(或操作)为中心,而不是以数据为中心。如果您的 API 调用专注于数​​据操作,那么您就有可能在客户端加载应该存在于服务器中的业务逻辑。您可能还会失去很多好东西,例如中间件(这对于横切关注点非常有用,例如权限和日志记录)。

【讨论】:

    猜你喜欢
    • 2013-01-15
    • 2015-11-09
    • 2019-06-09
    • 2011-04-12
    • 1970-01-01
    • 2012-11-28
    • 2010-11-24
    • 2011-01-01
    • 1970-01-01
    相关资源
    最近更新 更多