0

I'm trying to wrap a RESTful API around an existing implementation of a game.

Here is a possible state diagram of a simple API design that comes to mind:

enter image description here

I'm having troubles here because the existing domain implementation does not expose a list of moves. Instead it exposes the state of the whole board. A list of moves is not needed because the game does not support undos, or replays of games etc.

I can think of a few options:

  1. I drill open the existing domain implementation and have it expose a list of moves for each game. So that I can implement the design from the diagram above.

    I don't like this because having to change the existing domain model only to shoehorn it into an API has a bad smell.

  2. I design a state transition from /api/games/{id} with the extension relation newMove (or sth. similar) that allows a POST on the /api/games/{id}/moves resource. I will provide an API doc under /docs/rels/newMove. There won't be an implementation for GET on the list of moves.

    Is this still RESTful? Must every RESTful resource have a representation and allow GET?

    I find this appealing, though, because it means almost no additional server side logic.

  3. Of course there are more options. I could design the board as a sub-resource and implement a PUT state transition (+ link relation and docs) to update it.

    I don't like this either. It means that I have to transfer the whole board, including the new move. Putting the whole board back to the server and have the server find out, which field has changed and also validate that only one field has changed, and what not, is needlessly complex. And it would result in some amount of additional logic on the server. Which again smells bad. So maybe PATCH instead?

  4. Finally I could design the board as a sub-resource and every field of the board as a sub-resource of the board (e.g. /api/games/{id}/board/5/11) and then implement a PUT to make the move.

    This doesn't look bad. But it would be stupid to have the client get the state of the board by having it make multiple requests to get each field state. So there should probably be a representation of the complete board somewhere (e.g. /api/games/{id}/board or as a value of the game itself). In this case the question arises if it makes sense to implement GET for every field of the board at all because you ain't gonna need it.

    So here again, must every RESTful resource have a representation?

What is the simplest solution that still adheres to the REST constraints?

One of the options above or maybe something completely different?

  • Can you expand on why you need the server to return to the client a list of moves. Wouldn't the client already know the possible moves based on the rules of the game? The client should just need the state of the game, it updates that state and then PUTs that state back to the server – Cormac Mulhall Jan 17 '17 at 18:02
  • Putting the whole board back to the server and have the server find out, which field has changed and also validate that only one field has changed, and what not, is needlessly complex. Then I'd rather go for sth. like PATCH. As I said in the post, the client doesn't need a list of moves. This design came to my mind, because it is extremely simple and easy to make RESTful. – leifbattermann Jan 17 '17 at 19:21
1

I'm trying to wrap a RESTful API around an existing implementation of a game.

You should review Jim Webber's talk on REST and DDD, which I recommend primarily for his insights on REST

  • In HTTP, work is a side effect of passing documents around
  • The point of an HTTP API is to adapt your domain for the web

In particular, one of the advantages of hypermedia (one of the uniform interface constraints of REST), is that if a resource doesn't make sense, can't be implemented, whatever -- you just elide any links to that resource. Since the client only opens bookmarks and follows links, it's never going to go anywhere it shouldn't

Must every RESTful resource have a representation and allow GET?

No. See RFC 7231: OPTIONS.

What is the simplest solution that still adheres to the REST constraints? One of the options above or maybe something completely different?

If the space of candidate moves is small, you might be able to produce a list of allowed moves by simply trying them all. For example, a tic-tac-toe game only has 18 candidate moves in it; load up 18 copies of the current board, try each of the 18 moves, filter out of the list the moves the game rejects, and return the remainder.

Even in chess, in any given position there aren't too many moves to try -- using only the movement restrictions, a queen is reduced to at most 27 candidate moves, fewer for the other pieces, and you can of course ignore moves that would take the piece beyond the borders of the board.

Furthermore, you can take advantage of caching -- instead of providing a representation of the available moves for the current state of the game directly, you can re-direct the request to a resource that lists available moves in the current position. That calls for having a good way to represent the state of the board as part of a resource identifier, which may or may not be practical.

In a broader sense, if you are thinking about the representations that should be exchanged between the client and the server, then you should maybe consider event sourcing. For chess, the "document" that the players modify would be the score book -- on each play, the player makes an entry at the bottom of the ledger describing their next move; you can treat that as either a POST to the collection or a PUT to the position of the move itself. It's a bit truer to what is going on than having the client "make the moves" on its own copy of the board and then signalling to the server what the new state is.

0

You seem to be very focused on implementing some sort of strict RESTful API but REST has been implemented successfully in many different ways. I would focus on designing an API that is consistent and predictable for your specific domain.

From your options, I prefer 2 or 4 but it really depends on what this game's moves look like.

If you have a game like tic tac toe where you specify the board position and its new value, then your option 4 makes sense.

If you have a more complex game, your option 2 would allow more complex moves that didn't necessarily target a specific board position, Ex. moving 3 unit from (2,3) to (5,2), using unit located at (4,4) to reveal cell (8,10)

Remember to consider who will be using your api too. If it's easier for them to PUT the entire board to the server every move, it might be work the extra server logic to figure out what changed.

  • Yes RESTful is a constraint. Consistent and predictable is also good :) – leifbattermann Jan 17 '17 at 23:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.