Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTTP method for small actions such as a (up)vote

The verbs are pretty straightforward for CRUD actions.

What would be the right HTTP verb for only performing an action, something like an upvote?

Maybe this speaks more to data modeling? Is an upvote a resource or just an attribute? I'm unsure about that. Let's say it does modify the resource directly by calling #upvote on the model.

For example, if I upvote a question here on SO, what verb should be ideally used for that action? I am modifying the resource in a partial manner (PATCH?), but at the same time, I don't want to specify the new value as I could encounter concurrency issues, so this would best be managed by the database. In other words, we want to ask the server to perform an incremental action on a resource. Is that covered by PATCH?

I've seen a similar question asked there, but their case pointed to the creation of a new resource by viewing the job request as an object to be created. Are we in the same case here?

If the PATCH method really would be appropriate, what would it contain?

like image 228
Jonathan Allard Avatar asked Mar 15 '12 23:03

Jonathan Allard


1 Answers

Maybe this speaks more to data modeling? Is an upvote a resource or just an attribute?

Modelling impacts Implementation

We are usually modelling something from the real world and our choice of representation will seriously affect the capabilities of the developed system. We could implement our vote in two ways: as an attribute on the thing being voted on or as an entity in its own right. The choice will affect how easily we can implement desired features.


Two possible implementations ...


1. Votes as entities

I would model this with a resource which modelled the relationship between the voter and the thing being voted on. Why?

The vote has state:

  • what was being voted on
  • who voted,
  • when did they vote.
  • was it an up vote or a down vote (you mentioned SO as an example so I include that possibility here)

It is a resource in its own right with interesting behaviour around the votes

  • maintain a correct count of the votes
  • prevent multiple up votes / down votes


It can be modelled easily with REST.

I can POST/PUT a new vote, DELETE a previous vote, check my votes with a qualified GET.

The system can ensure that I only vote once - something which would not be easy to do if a simple counter was being maintained.


2. Votes as an attribute

In this implementation, we model the vote as a counter. In this case we have to

  1. Get the entire state of the thing being voted on - maximising the interface between client and server

  2. Update the counter

  3. Put back the updated state - oops, someone already updated the resource in the meantime!

The server now has no easy way to handle multiple votes from the same person without managing some state 'on the side'. We also have that 'lost update' problem.

Things quickly get complicated.


Final advice

The decision on how you model something should be driven by what you need the system to do.

There is often no correct decision, just the best compromise between effort and value.

Choose a design which most easily implements the most common Use Cases. Common things should be quick and simple to do, uncommon things need only be possible.


Chris

like image 97
Chris McCauley Avatar answered Nov 15 '22 22:11

Chris McCauley