REST - 模型状态转换

5
REST - 可撤销的DELETE 中,介绍了如何在REST中建模状态变化。基本上,如果你有一个带有字段status的资源,你只需放置一个新版本的该资源,并更新status字段。

在这个主题中,我想扩展这个模型。假设你有一个可以处于两种状态1和2的资源。与引用帖子中描述的简单模型相反,从状态1到状态2有三个转换要遍历,而不仅仅是一个。

我的问题是:你会如何在REST中建模状态转换?

我自己想不出类似于RPC的POST方式,这可能不是很符合REST规范:

POST http://server/api/x
     target_state=2&transition=3

使用转移3,将资源x从状态1更改为状态2。

1个回答

2

这并不仅限于REST;这实际上是关于状态机的基本问题。状态机应该封装所有状态,因此如果您发现自己从一个状态到另一个状态创建了多个转换,并且差异很大,那么这种差异必须在状态中被捕获。

例如,假设我没有家。我可以通过三种方式从“无家可归”状态转移到“家庭”状态:我可以租一个、买一个或偷一个。从“无家可归”到“家庭”的三次转换?对于机器来说并不存在这样的情况。要么差异显著,要么不显著。如果它们不显着,则对于机器而言,根本没有区别。只需将新状态“家”进行PUT操作即可。如果它们是显着的,则我们需要扩展我们的状态概念以涵盖差异。例如:

         homeless
        A    A   A
       /     |    \
      V      |     V
possessor <--|---  renter
       A     |    /
        \    |   /
         V   V  V
           owner

我可以通过偷房子从无家可归变成有房产的人。如果我足够长时间占据它,我可能会成为房主。或者我可以是无家可归的人租一间房子,甚至是租购。或者我可以直接购买一间房子。这三条路径都让我达到了“所有者”的状态,但它们使用中间状态来表示显著不同的转换。
如果你想要表示“无家可归”与“有住所”(拥有者|租户|所有者)之间的区别,那么将其作为只读计算资源公开出来就没有问题。只是不要让任何人PUT/POST它,因为这种转换是模糊的。如果该状态具有重要意义,保留状态转换历史记录也没有问题。

首先,非常感谢您详细的回答。非常好。但我仍然不太相信每个转换都可以轻松地建模为状态。我认为中间状态和永久状态之间存在巨大差异。你涵盖了第二组。关于第一组,举个例子:假设你可以通过3种方式从无家可归到拥有者:付款购买、继承或在抽奖中赢得。你也要将其建模为单独的状态吗?这不是会导致“只为表示不同的转换而产生大量的状态”吗?您怎么看待这个问题? - Zure Citroen
“通过‘所有者’我指的是‘被盗’。如果你付钱购买或在彩票中赢得它,那么你就处于‘所有者’状态。” 如果这对您的应用程序很重要,那么是的,您应该使用中间状态、创建新的终端状态或添加附加状态(如抵押贷款的资源)来表示差异。 - fumanchu
好的,明白了。我只是担心由所有可能的转换的叉积生成的“虚拟”状态会爆炸。 - Zure Citroen
1
@ZureCitroen - 再次强调,最终关键在于你关心什么。如果你真的关心所有转换的交叉积中的每个虚拟状态,那么你应该将转换变成状态。如果你不关心它们,那么它们只是转换。在状态机中,状态很重要,而不是转换。转换只是达到目的的手段。 - cdeszaq

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接