前几天我在看维基百科(和你一样),发现了状态转换表。
基本上,状态转换表显示了状态机如何在不同的状态之间转换,它是绘制状态图的另一种选择,可以帮助您找到逻辑中的漏洞。
维基百科显示了一些非常抽象的表格,所以我将以自动售货机为模型。为了简化起见,我们将在一个季度内提供一种饮料。与这台机器(快乐之路)互动的理想化版本是:
要实现这一点,我们必须管理两个独立的状态:您是否已将钱放入自动售货机,以及是否有至少一种饮料可供自动售卖。
让我们用一维状态转换表对上面的交互进行建模。只使用一个维度可以使建模尽可能简单,同时仍能捕捉到足够多的有用细节:我们有一列,分别用于输入、当前状态、下一个状态和副作用。要了解事件发生后会发生什么,您只需找到您关心的输入和当前状态行,然后查看匹配的下一个状态和副作用。对于我们的自动售货机,可能如下所示:
但是,当然,我们必须模拟当我们做一些不愉快的事情时会发生什么。不幸的是,表格的一维版本并没有给我们提供一个很好的视图!
为了找出我们哪里有洞,我们需要添加更多的维度。让我们沿着垂直轴重新组织我们的状态,并沿着水平轴重新组织输入,以得到一个二维状态转换表。
要读取此表,请将沿垂直轴的当前状态与沿水平方向的输入进行匹配。我们的下一个状态和副作用位于交叉点(我已用/分隔它们):
我们看到,呃...。问题。当我们这样看待事物时,很明显,我们只定义了8种可能结果中的两种!有序地写下事情表明,我们没有详细说明我们的建模所隐含的所有可能性。
让我们把剩下的填了吧。为了让事情变得容易些,当国家保持不变或者没有副作用时,我标出了--。
但当我们填写表格时,我们会发现我们遇到了一个潜在的奇怪情况:如果我们不知何故有一些钱,但没有饮料怎么办?状态机应该会阻止这种情况,因为没有新的州字段可以造成这种情况。但是,通过编程(例如,通过将州建模为两个独立的字段)或硬件问题(例如,有人撬开机器离开宿舍,这是一种非典型的破坏行为)是可行的。
在我们进入应用程序的代码部分之前,我们的建模已经揭示了这种未定义的行为,而最困难的部分是制作一个表并寻找空单元格。现在,我可以将相同的表带给利益相关者或领域专家,并就他们认为应该发生的事情进行富有成效的对话。
(哦,还有一个好处:如果您正在使用ELM,这里的一维表单可能非常熟悉。";Input、Current State、Next State、Output和UPDATE的作用相同:msg->;model->;(model,cmd msg)!)