سؤال

I'm fairly new to REST web services and very used to RPC. I know the advantages of REST by reading several posts like this one.

I am developing the server in django using django-rest-framework.

Although have this question (or questions):

I have this model:

class Poll(models.Model):
    questionString = models.CharField(max_length=500, blank=True)
    timeToAnswer = models.IntegerField(default=30)
    startDate = models.DateTimeField(null=True, db_column='startDate', blank=True)
    token = models.CharField(max_length=20, blank=True, unique=True)

class PollAggregator(models.Model):

    name = models.CharField(max_length=135)
    description = models.CharField(max_length=500, blank=True)
    votersToken = models.CharField(max_length=20, null=True, blank=True)

class PollPollAggregatorRel(models.Model):
    pollAggregator = models.ForeignKey(PollAggregator, null=True, db_column='pollAggregatorId', blank=True)
    poll = models.ForeignKey(Poll, null=True, db_column='pollId', blank=True)

So I can have a single poll or I can have a bunch of polls aggregated in a poll aggregator (i.e. room).

So I created the rest calls: pollList, pollDetail, pollAggregatorList, pollAggregatorDetail. But I have problems to design for PollPollAgregatorRel. Of course I can have PollPollAgregatorRelList and PollPollAgregatorRelDetail and make the normal post, get, update, delete. So if I want to make a new relation between a poll and poll aggregator in REST style, I do:

  • Check if PollPollAgregator (list) exists with the poll id with a get and filtered by pollId
  • If so, I update this item to have my new pollAggregator id
  • If not I create a new PollPollAgregator with a post

My first question is is there any easier and simpler way to do this?

If I use a RPC like web service I do something like:

  • Relate poll with pollAggregator and use a get_or_create for PollPollAggregatorRel. So I update or create a new PollPollAggregatorRel object.

So using RPC like, the client uses only one call versus REST that needs to call 2 times. In this case seems to be much simpler to use RPC for both server and client side.

Second question is: Is it bad practice to use both REST and RPC in the same API?

هل كانت مفيدة؟

المحلول

Q1: I think it would be reasonable to provide a REST-style POST operation that either returns an existing aggregator or creates a new one as required. Which, logically, seems not unlike your "RPC" service.

I think part of your difficulty may be that you are designing your REST "calls" (hint: they're not "calls", they're "resources") too closely around the underlying model. It's a mistake I've made in the past.

REST != CRUD.

A key benefit of REST is that it allows the interface to be separated from the model, so the server can change its implementation without affecting clients. Another key benefit is that it minimizes the amount of information the client needs to know in advance in order to perform some operation. E.g. a REST client should be able to discover all the resource URIs it needs to use by interacting with the "front resource" (by analogy with "front page") of the service.

So I would consider an approach in which there the following resources cover what you describe above:

  1. a service home page, whose representation contains links (or link templates) to the other resources (or returns links via HTTP Link headers)

  2. a "poll collection" resource which provides for creation and access to individual polls (e.g. GET returns list of all polls, POST creates a new one)

  3. individual polls, whose URIs are discovered though interactions with the "poll collection". GET, PUT, DELETE do as you might expect. I'm not sure if you'd need POST for these.

  4. an "aggregation manager" resource that associates polls with aggregations (can a poll belong to more than one aggregation? - your description suggests not). A POST to this resource containing a POLL URI could locate-or-create an aggregation (or aggregations?) or create a new one. GET might return a list of existing aggregations.

  5. individual aggregation resources whose URIs are discovered though interactions with the aggregation manager resource.

In your description, the PollPollAggregatorRel is part of your (current) implementation, not something you expose as such through the REST API. This gives you flexibility to change your internal implementation without affecting how clients use the API. That's the point of REST.

I'm not sure if you'd regard this as "easier and simpler", but that's not the point of REST. REST has been described by Roy Fielding as "software engineering on a scale of decades", and the point is to create an interface that allows relatively independent evolution of client and server implementations, which is crucial for an application that operates at web scale. There is a price to pay for this, which is that the client has to interact with the server to discover information it needs to progress an interaction.

Q2: I would not consider it sensible to mix REST and RPC in the same API. (It might make perfect sense to expose REST to external; clients and use RPC internally, or to offer separate APIs.)

My rationale for this is that if you have a mostly REST API, adding an RPC element potentially creates a tight coupling between client and server that rather negates the point of using REST in the first place.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top