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

69 views Asked by At

This is a general question, I'm making an example just to better illustrate what I mean.

Assume I have a User model, and a Tournament model, and that the Tournament model has a key/value map of user ids and their scores. When exposing this as a GraphQL API, I could expose it more or less directly like so:

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

This gives access to all the data. However, in many cases it might be useful to get a user's scores in a certain tournament, or going from the tournament, get a certain user's scores. In other words, there are many edges that seem handy that I could add:

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

This would probably be more practical to consume for the client, covering more use cases in a handy way. On the other hand the more I expose, the more I have to maintain.

My question is: In general, is it better to be "generous" and expose many edges between nodes where applicable (because it makes it easier for the client), or is it better to code sparingly and only expose as much as needed to get the data (because it will be less to maintain)?

Of course, in this trivial example it won't make much difference either way, but I feel like these might be important questions when designing larger API's.

2

There are 2 answers

0
Ahmad Ferdous On BEST ANSWER

I could write it as a comment but I can't help emphasizing the following point as an answer:

Always always follow YAGNI principle. The less to maintain, the better. A good API design is not about how large it is, it's about how good it meets the needs, how easy it is to use.

You can always add the new fields (what you call edge in your example) later when you need them. KISS is good.

1
Ruslan Talpa On

Or you could do this

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

and since user_ids and tournament_ids are not mandatory, a user can make the decision to get all edges, some, or one.