首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无处不在的语言和基于资源的REST?

无处不在的语言和基于资源的REST?
EN

Software Engineering用户
提问于 2016-06-15 09:19:49
回答 2查看 398关注 0票数 4

我发布了一个关于REST中无处不在的语言和成熟度级别的问题。

REST中无处不在的语言和成熟度级别?

经过一些广泛的编码,我意识到可以从这篇文章中得到更多的问题。

例如,如果我使用的是基于资源的API,那么API端点在基本GET中看起来就像http://domain.com/products/555

如果我想更新一个资源,它应该如下所示

http://domain.com/products/555 PUT

期待一个有效负载,例如

代码语言:javascript
复制
{
id: 555,
name: "Sample product",
availability: 111
}

为了使用DDD和普适语言的所有功能,域模型应该包含以下方法:

  • UpdateProductName
  • ChangeAvailability
  • BlockProductFromFurtherSale等。

因此,如果API期望这个有效负载,我正在考虑两个可能的解决方案。

( a)将此单个更新端点拆分为多个,如:

  • http://domain.com/products/555/UpdateProductName PUT { id: 555,名称:“示例产品”}
  • http://domain.com/products/555/ChangeAvailability放置{ id: 555,可用性: 111 }
  • http://domain.com/products/555/BlockProductFromFurtherSale放置{ id: 555 }

b)在应用层中有额外的逻辑,以便

  • 比较当前域和新的有效载荷
  • 检测更改并需要更新的值。
  • 根据更改的值调用适当的域方法

有什么推荐的方法来处理这个场景吗?

EN

回答 2

Software Engineering用户

发布于 2016-06-15 12:22:54

我将尽量详尽地介绍您可能使用的解决方案。正如您所写的,我认为产品具有以下属性: id、名称、可用性

1.为每个属性

设计一个资源

  • /products/ 555 / name:GET返回产品id 555的当前名称。PUT newnamenewname修改产品id 555的当前名称
  • /products/555/ availability:GET返回当前可用性。PUT 99修改99的当前可用性。

..。等等..。

请注意,这些资源不是“面向方法的”,它们对应的概念(产品的名称、可用性等)可以更新、检索、删除等,并且不受特定功能的限制。

还请注意,当资源接收GETPUT请求时,我没有描述不同的内部方法调用。这完全是正交的。在答案的末尾,我会给它写个小便条。

这种方法的主要缺点是:要更新x属性,客户端需要发送x个请求。您可以清楚地看到,客户端这样做可能很乏味,而且带宽消耗也很大。但如果没问题,那就去吧。

2.具有所有属性

的资源

  • /products/555 :包含产品的每个属性(名称、可用性等)。GET返回这些属性。要更新它们,您有两种可能:

2.1使用PUT

进行更新

PUT方法旨在完全更新资源表示形式。这意味着客户端需要发送有效负载中产品的所有属性。

假设当前资源/产品/555的表示是:

代码语言:javascript
复制
{ "name": "bread", "availability": 10 }

如果只想更新到99的可用性,则需要发送资源的完整表示形式,如下所示:

代码语言:javascript
复制
PUT /products/555 { "name": "bread", "availability": 99 }

这种方法的主要缺点是:希望更新一个字段的客户端需要发送整个资源表示。

2.2使用修补程序

进行更新

补丁动词旨在部分更新资源表示形式。考虑到当前产品的表示形式是{ "name": "bread", "availability": 10 }。如果客户端只想更新availability,它将发送:

代码语言:javascript
复制
PATCH /products/555 { "availability": 42 }

小心点,因为补丁不是幂等的。这意味着这一请求:

代码语言:javascript
复制
PATCH /products/555 { "availability": 42 }

可以产生以下资源表示:

代码语言:javascript
复制
{ "name": "bread", "availability": 42 }

代码语言:javascript
复制
{ "name": "sugar", "availability": 42 }

因此,它破坏了幂等性..。PUT保证:)!(因为使用PUT,您可以在请求体中发送完整的表示)

如果产品资源有,您还可以更新几个属性。这显然比1中描述的解决方案消耗的带宽要少。

注释:底层方法调用

如前所述,方法调用与资源的设计是正交的。

在您的例子中,您有一些细粒度的方法来更新Product的一个属性.没关系。

但是您可以将它封装在粗粒度的方法中,如下所示:

代码语言:javascript
复制
Product updateProduct(Product p) {
  p.updateName();
  p.changeAvailability();
  ...
  return p;
}
票数 3
EN

Software Engineering用户

发布于 2016-06-15 13:01:50

有什么推荐的方法来处理这个场景吗?

您需要查看Jim关于Restful系统 DDD的讨论。

基本方案--修改聚合,将文档(也称为消息)传递到HTTP端点,而对聚合所做的更改是文档操作的副作用。

因此,解决方案(a)正朝着正确的方向发展。

我认为,每个命令都应该有一个单独的资源--我的意思是,您应该能够区分重复命令和两个参数相同的命令(在愉快的路径上,这并不重要--但如果您在不可靠的网络(如TCP/IP)上发送命令,则可能很重要)。

实际上,这意味着每个命令都有自己的、客户端生成的唯一标识符,这个标识符在URI中使用,就像产品id用于标识产品资源一样。

因为每次都要传递命令的完整表示形式,所以适当的方法是PUT (或者post,如果PUT不支持的话)。

在此之后,这只是URI设计的问题;但必须满足URI必须弥补您选择从消息本身的正文中删除的任何数据的约束。但以下任何一项都可能是合适的

代码语言:javascript
复制
PUT /commands/a3a14d61-5343-442f-8c2b-febc4d9d8164
PUT /products/555/commands/a3a14d61-5343-442f-8c2b-febc4d9d8164
PUT /products/555/{commandType}/a3a14d61-5343-442f-8c2b-febc4d9d8164
PUT /products/555/commands/{commandType}/a3a14d61-5343-442f-8c2b-febc4d9d8164
PUT /products/555/{commandType}/commands/a3a14d61-5343-442f-8c2b-febc4d9d8164

休息不关心什么颜色的自行车棚是,所以去与任何最适合你现有的指导方针。

票数 1
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/322282

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档