Design the API

Dilemmas while designing API

On the sign-in screen, the user will submit a name and a language choice. Where does the list of language options come from? We could have the front-end application contact the server to find out the valid language options to show. This requires an additional API request, but we’ll be able to update the list without resetting all clients. Or, we could hard-code the options into the front-end application, making them part of the code itself. To update the list, we need to make sure every browser gets the new client. To simplify this, we could have every API response also return a field, indicating if there’s a new client available, although this goes against the spirit of the REST API because it contaminates each route with unrelated responsibilities. This sort of design question about how updates are handled is an important part of API design. Since we anticipate that language options will only rarely change, we will leave the options hard-coded in the client.

Sign-in screen methods

What is the resource and method most appropriate for the response from this first screen? Since starting a game alters data, it cannot be a GET. Is it idempotentidempotent means that doing the action twice has the same net effect as doing it just once? PUT actions are idempotent whereas, POST actions are not. Since each time a game is started, a new game state is created and a random word is selected, starting is not idempotent. Therefore, it should use the POST method. The resource will be /games, as it is starting a game. We have a choice in how the user’s name and the language fit into the API call. Should they be part of the route or sent as the payload? The language option seems like a parameter that belongs in the payload. We do not think of the English collection of games as a resource. If we did, then it would make sense to query that collection. An argument could be made that the game belongs to the user, so the actual resource would be /<user_name>/games or /<user_name>. It’s typical, as in this example, for there to be a gray area of what is a resource and what is a payload. When in doubt, think of the information as adjectives and resources as nouns, and we should put it in the payload.

This argument suggests that the right way to begin a game is to post to /games, where the payload includes the user’s name and the language selection. In response, the server should create a game, that is, choose a usage example and a word, which is a new item in the /games collection, and return the unique identifier for that game. We will then expect the resource for that particular game to be /games/<game_id>.

Game screen methods

In the guess-a-letter screen, the interactions with the server are all of the same kind. The client submits a letter. Again, we ask ourselves, what is the resource and what is the action? One could imagine a game itself being viewed as a collection, and letters being individual items within the game collection.

This would work, but having a resource be an individual letter is a bit too fine-grained. It’s more natural to continue thinking about the game as the resource and submitting a letter as an alteration of that game. It could be a POST or a PUT. If the same letter is guessed twice, then it should have no effect the second time, because it’s already been revealed as part of the word or the penalty has already been counted.

Therefore, as guessing a letter is idempotent, we can use the PUT method. Since it acts on the game itself, the route would be /games/<game_id>. It should return enough information so that the client knows what to do. In particular, it must specify if the guess was already made, in which case nothing happens, or if the guess was a new correct or incorrect guess, in which case the blanks and Gallows get updated, and also whether the game has ended, so the client can move on to the next screen). Also, the client will be tracking the letters used so the buttons can be updated accordingly. Finally, we will add a live link on the Lang-Man title that takes the user back to the first screen from the letter guessing screen. From the API perspective, this could delete the current game.

Win or lose screen methods

If the game goes to the win-outcome or lose-outcome screens, then the buttons allow the user to play again, which will resend a POST to the server, using the current user name and a possibly new language option. If the user clicks the “quit” button, then no API interaction is required. The username is erased and the client returns to the sign-in screen.

Summary of methods in our App

These routes describe POST, PUT, and DELETE methods. In summary, this simple web application has only three methods that need to be supported. For completeness, we add a GET method that provides the current game status.

Get hands-on with 1400+ tech skills courses.