嵌套突变会有多糟糕?

How bad would it be to have nested mutations?

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

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,
  }
}

如果你在 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. You can find another example in the documentation 所示。

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

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

比如一个团队只能有10个人,而且已经达到了上限。撰写操作应该完全失败吗?我们应该只添加用户而不是将其添加到团队中吗?响应会是什么样子?

Second,以这种方式合并两个操作可能会暴露应用程序逻辑。人们可能会想使用这样的突变来执行 'When X happens Y should also happen as well'。例如,在向发票添加新行时,总数应该更新。这真的应该发生在一个变化中,addLineToInvoice,并且逻辑驻留在服务器上。

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