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

Rod*_*Gil 5 django rest rpc django-rest-framework

我是REST Web服务的新手,非常习惯于RPC.我通过阅读像这样的几个帖子来了解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)
Run Code Online (Sandbox Code Playgroud)

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

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

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

我的第一个问题是有没有更容易和更简单的方法来做到这一点?

如果我使用类似RPC的Web服务,我会做类似的事情:

  • 使用pollAggregator进行轮询,并使用get_or_create进行PollPollAggregatorRel.所以我更新或创建一个新的PollPollAggregatorRel对象.

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

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

Gra*_*yne 7

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

我认为你的部分困难可能是你正在设计你的REST"呼叫"(提示:它们不是"呼叫",它们是"资源")过于紧密地围绕底层模型.这是我过去做的一个错误.

REST!= CRUD.

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

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

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

  2. "poll集合"资源,用于创建和访问各个民意调查(例如,GET返回所有民意调查的列表,POST创建一个新民意调查)

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

  4. 一个"聚合管理器"资源,它将轮询与聚合相关联(轮询是否属于多个聚合? - 您的描述不建议).包含POLL URI的此资源的POST可以找到或创建聚合(或聚合?)或创建新聚合.GET可能会返回现有聚合的列表.

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

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

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

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

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