2

My question is about when it's OK to merge separate models into one single REST resource and whether this leads to tricky and difficult to work with design, down the line.

Let's say I have a movie streaming service and users can only watch movie genres they have permissions for. Let's say these are represented with these hypothetical models:

  • users (id)
  • movie_genres (id, genre_name)
  • users_to_genres_permissions (id, genre_id, user_id)

exposed through REST routes /users /movie_genres and /users_to_genres_permissions

Now, as a user client of this API (think a website or a mobile app), in order to find out what genres I'm allowed to get hold of, I would fetch the genres permissions and then all the movie genres. Two network calls.

However, an argument could be made that having to make multiple round-trips to the API is inefficient, and you additionally have to deal with a bunch of joins on the client. This example is simple enough with its 3 relations, but in the real world you could have much longer chains.

Thus one could consider collapsing two models into one, and for example return permissions already joined to movie genres:

movie_genres (id, genre_name, authorized_for_current_user)

However the question is, this thought process can be taken pretty far. You could save the client a lot of joins and round-trips by doing all joining on the server. However, at what point do you stop? At what point is what you returning no longer a REST resources but a generic blob of data that's been concatenated together?

Is there a rule of thumb for deciding where to draw the line?

Alexandr Kurilin
  • 7,685
  • 6
  • 48
  • 76
  • The following link give the basics about DB normalization: http://databases.about.com/od/specificproducts/a/normalization.htm – Nir Alfasi Aug 16 '13 at 21:30
  • alfasin, the question is not so much about the DB side as about the API client side of things. It's safe to assume that the API client is completely oblivious to the internals of the API. – Alexandr Kurilin Aug 16 '13 at 21:37

1 Answers1

0

REST stands for Representational State Transfer. From wiki:

Requests and responses are built around the transfer of representations of resources. A resource can be essentially any coherent and meaningful concept that may be addressed. A representation of a resource is typically a document that captures the current or intended state of a resource.

As such, RESTful web-services provide access to resources, which means, that any API call should concentrate on one resource - and that should be your "rule of thumb".

The example that you posted is very basic, but if you'll add more entities, such as: movie-producers, actors, media-companies etc, then each request should handle only one entity. That said, your backend would need to handle requests that will require it running JOINs, for example, movies recommendations for user X. But don't let it confuse you - the request should be very simple and the response should include a "list" of objects of type movie (only one entity!).

Nir Alfasi
  • 53,191
  • 11
  • 86
  • 129
  • The fact is that you can create a separate resource for every underlying join. actors_in_movie resource, producers_in_movie resource etc. Should you? Should you avoid it? Some choose to handle this through nested resources as well. – Alexandr Kurilin Aug 16 '13 at 22:16
  • If you have one-to-many relationship then you probably should create a new table. If it's one-to-one you can just add another column in the relevant table. If you decide to work with un-normalized data - it'll be easier to `select` but the maintenance will be trickier (i.e. triggers, constraints, transactions etc). – Nir Alfasi Aug 16 '13 at 22:34
  • You just present the resources that clients may be interested in, and the model that defines the presentation of your resources does not have to perfectly match the business model underlying your service. – tuespetre Aug 17 '13 at 02:47
  • I know I should do a POST with a resource in the request body, so as to add in a join relationship, but I want to pass only the two property identifiers (their id) and not the two whole property objects, making it simpler to the client. – Stephane Sep 16 '14 at 19:19