在 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_ids
和 tournament_ids
不是强制性的,用户可以决定获取所有边缘,部分边缘或一个边缘。
这是一个普遍的问题,我举个例子只是为了更好地说明我的意思。
假设我有一个用户模型和一个锦标赛模型,并且锦标赛模型有一个 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_ids
和 tournament_ids
不是强制性的,用户可以决定获取所有边缘,部分边缘或一个边缘。