将REST和RPC混合在一起是不好的做法?

时间:2014-03-11 10:08:34

标签: django rest rpc django-rest-framework

我对 REST Web服务相当新,并且习惯于 RPC 。通过阅读this一个帖子,我知道 REST 的优点。

我正在使用django-rest-framework在django中开发服务器。

虽然有这个问题(或问题):

我有这个型号:

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)

所以我可以进行一次民意调查,或者我可以在民意调查聚合器(即房间)中汇总一堆民意调查。

所以我创建了其余的调用:pollList,pollDetail,pollAggregatorList,pollAggregatorDetail。但是我在为PollPollAgregatorRel设计时遇到了问题。 当然我可以使用PollPollAgregatorRelList和PollPollAgregatorRelDetail进行正常发布,获取,更新,删除。因此,如果我想在REST样式中建立一个poll和poll聚合器之间的新关系,我会这样做:

  • 检查PollPollAgregator(列表)是否存在,其中轮询ID带有get并通过pollId过滤
  • 如果是这样,我更新此项目以获得我的新pollAggregator id
  • 如果不是,我用帖子
  • 创建一个新的PollPollAgregator

我的第一个问题是,有没有更容易和更简单的方法呢?

如果我使用类似RPC的Web服务,我会执行以下操作:

  • 使用pollAggregator进行民意调查,并使用get_or_create进行PollPollAggregatorRel。所以我更新或创建了一个新的PollPollAggregatorRel对象。

因此,使用RPC之类的,客户端只使用一次调用而不是需要调用2次的REST。在这种情况下,对服务器端和客户端使用RPC似乎要简单得多。

第二个问题是:在同一个API中同时使用REST和RPC是不好的做法吗?

1 个答案:

答案 0 :(得分:6)

Q1:我认为提供REST样式的POST操作是合理的,该操作要么返回现有的聚合器,要么根据需要创建新的聚合器。从逻辑上讲,这似乎与你的" RPC"服务。

我认为你的部分困难可能在于你正在设计你的REST"电话" (暗示:他们并没有"电话"他们"资源")围绕底层模型过于紧密。这是我过去犯过的错误。

REST!= CRUD。

REST的一个主要优点是它允许将接口与模型分开,因此服务器可以在不影响客户端的情况下更改其实现。另一个主要好处是它可以最大限度地减少客户需要提前知道的信息量,以便执行某些操作。例如。 REST客户端应该能够通过与"前端资源"进行交互来发现它需要使用的所有资源URI。 (通过类比"首页")服务。

所以我会考虑一种方法,其中以下资源涵盖了您在上面描述的内容:

  1. 服务主页,其表示包含与其他资源的链接(或链接模板)(或通过HTTP链接头返回链接)

  2. a"民意调查集"提供创建和访问个人民意调查的资源(例如,GET返回所有民意调查的清单,POST创建一个新的民意调查)

  3. 个人民意调查,其URI是通过与"民意调查集合"的互动而发现的。 GET,PUT,DELETE按照您的预期进行操作。我不确定你是否需要POST这些。

  4. "聚合经理"将民意调查与聚合相关联的资源(民意调查可以属于多个聚合吗? - 您的描述不建议)。包含POLL URI的此资源的POST可以找到或创建聚合(或聚合?)或创建新聚合。 GET可能会返回现有聚合列表。

  5. 通过与聚合管理器资源的交互发现其URI的各个聚合资源。

  6. 在您的描述中,PollPollAggregatorRel是您(当前)实现的一部分,而不是您通过REST API公开的内容。这使您可以灵活地更改内部实现,而不会影响客户端使用API​​的方式。这是REST的重点。

    我不确定你是否认为这更简单,更简单"但这不是REST的重点。 REST已被Roy Fielding描述为"数十年的软件工程"并且重点是创建一个允许相对独立的客户端和服务器实现演变的接口,这对于运行的应用程序至关重要在网络规模。需要为此付出代价,即客户必须与服务器交互以发现进行交互所需的信息。

    Q2:我认为在同一API 中混合使用REST和RPC 是不明智的。 (将REST暴露给外部客户端并在内部使用RPC或提供单独的API可能是完全合理的。)

    我的理由是,如果你主要使用REST API,那么添加一个RPC元素可能会在客户端和服务器之间产生紧密耦合,而不是首先否定使用REST的重点。