在 GraphQL API 中应该谨慎还是大量添加字段?

Should fields be added sparingly or generously in a GraphQL API?

这是一个普遍的问题,我举个例子只是为了更好地说明我的意思。

假设我有一个用户模型和一个锦标赛模型,并且锦标赛模型有一个 key/value 用户 ID 及其分数映射。当将其作为 GraphQL API 公开时,我可以或多或少地像这样直接公开它:

Schema {
  tournament: {
    scores: [{
      user: User
      score: Number
    }]
  }
  user($id: ID) {
    id: ID
    name: String
  } 
}

这可以访问所有数据。然而,在许多情况下,获取某个用户在某个锦标赛中的分数,或者从锦标赛中获取某个用户的分数可能是有用的。换句话说,我可以添加许多看起来很方便的边:

Schema {
  tournament: {
    scores: [{
      user: User
      score: Number
    }]
    userScore($userID: ID): Number   # New edge!
  }
  user($id: ID) {
    id: ID
    name: String
    tournamentScore($tournamentID: ID): Number   # New edge!
  } 
}

这对于客户来说可能更实用,以方便的方式涵盖更多用例。另一方面,我暴露的越多,我就越需要维护。

我的问题是: 一般来说,"generous" 并在适用的情况下暴露节点之间的许多边缘是否更好(因为它使客户端更容易) ,还是少写代码,只公开获取数据所需的数量更好(因为维护起来会更少)?

当然,在这个微不足道的例子中,这两种方式都不会有太大区别,但我觉得在设计更大的 API 时,这些可能是重要的问题。

我可以把它写成评论,但我不得不强调以下几点作为答案:

永远永远跟随YAGNI principle。维护越少越好。一个好的API设计不在于它有多大,而在于它能很好地满足需求,它有多容易使用。

您可以随时在以后需要时添加新字段(在您的示例中称为边缘)。 KISS很好。

或者你可以这样做

Schema {
  tournament: {
    scores(user_ids: [ID]): [{
      user: User
      score: Number
    }]
  }
  user($id: ID) {
    id: ID
    name: String
    tournaments(tournament_ids: [ID]): [{
      tournament: Tournament
      score: Number
    }]
  } 
}

并且由于 user_idstournament_ids 不是强制性的,用户可以决定获取所有边缘,部分边缘或一个边缘。