状态机:确定下一状态的多种条件?

时间:2018-01-08 02:06:56

标签: c# state-machine stateless

请参阅TL的结尾; DR。

考虑一个简单的杂志文章发布工作流程。下图显示了对该过程的基本概念性理解,我们希望将其转换为代码(在本例中使用Stateless)。它涵盖了出版物的基本“快乐路径”,以及一些可能的问题:

┌───┬──────────────────────────────────────────┐
│ W │    ┌───────────┐                         │
│ r │    │           │                         │
│ i │    │   Write   ◄────────┐                │
│ t │    │           │        │                │
│ e │    └───────────┘        │                │
│ r │          │              │                │
├───┼────────Submit───────────│────────────────┤
│   │          │              │                │
│   │    ┌─────▼─────┐        │                │
│   │    │           │        │                │
│   │    │  Review   ◄──────┬─│──────────┐     │
│   │    │           │      │ │          │     │
│   │    └───────────┘      │ │          │     │
│   │          │            │ │          │     │
│   │      ____▼___         │ │          │     │
│ E │     /        \        │ │          │     │
│ d │    /  Grammar \───No──│─┘          │     │
│ i │    \    OK?   /       │            │     │
│ t │     \________/        │         Resolve  │
│ o │          │           Date          │     │
│ r │         Yes         Passed         │     │
│   │          │            │            │     │
│   │      ____▼___         │            │     │
│   │     /        \        │            │     │
│   │    /   Libel  \────Yes│────────┐   │     │
│   │    \   Risk?  /       │        │   │     │
│   │     \________/        │        │   │     │
│   │          │        ┌───│───┐    │   │     │
│   │          No       │ Defer │    │   │     │
│   │          │        └───▲───┘    │   │     │
│   │      ____▼___         │        │   │     │
│   │     /        \        │        │   │     │
│   │    / Embargo? \─Yes───┘        │   │     │
│   │    \          /                │   │     │
│   │     \________/                 │   │     │
│   │          │                     │   │     │
├───┼──────────No────────────────────│───│─────┤
│ L │          │                     │   │     │
│ e │          │               ┌─────▼───│─┐   │
│ g │          │               │   Legal   │   │
│ a │          │               │  Review   │   │
│ l │          │               └───────────┘   │
├───┼──────────│───────────────────────────────┤
│ P │          │                               │
│ r │    ┌─────▼───────┐                       │
│ i │    │             │                       │
│ n │    │  Print it!  │                       │
│ t │    │             │                       │
│ e │    └─────────────┘                       │
│ r │                                          │
└───┴──────────────────────────────────────────┘

我的问题是如何考虑状态转换,特别是编辑完成审核后的转换。

一种方法(A)将责任放在用户身上以选择适当的转换;所以在这种情况下,编辑器会有一个名为Revert to Check SpellingRefer for Legal ReviewDefer Publication的单独按钮。这些将连接到Article对象上的相应方法,该对象在.Fire(...)上内部调用_stateMachineTriggers,每the recommended approach

然而,至少有两个缺点。首先,它增加了用户的认知负担(在这种情况下,边缘,但为了示例,请留在我身边)。她不应该选择做什么,她应该能够一次性完成所有数据输入,在这样的表格上:

┌─────────────────┬──────────────────────┐
│ Spelling OK?    │ Yes [ ]   No [ ]     │
│ Libel Risk?     │ Yes [ ]   No [ ]     │
│ Embargo?        │ Date [ dd/mm/yyyy ]  │
└─────────────────┴──────────────────────┘

然后应用程序应该决定做什么。这也会阻止用户做出错误的选择:更容易回答有关内容的事实问题,而不是根据潜在的许多输入决定正确的行动方案(想象一个更复杂的例子)。

第二个缺点是审核可能会过早中断:只要找到一个问题并触发相应的操作,编辑就无法继续审核以发现其他问题。一旦第一个问题得到解决并且文章再次回来进行审核,它实际上将从头开始。

我看到的另一个建议(B)是建模更多状态:Grammar Issue状态,Contains Libel状态等等。然而,这又回到了同样的问题:用户必须单独触发向这些状态的转换(假设并非所有这些问题都可以通过例如语法检查器等自动确定。)

此外,这感觉就像远离我们相对干净的世界模型,或者至少从国家机器库提供的​​假设清洁度。想象一下,在一个更复杂的例子中,状态的激增,用户输入更多的变量。我期待使用无状态的export to DOT graph功能来实现代码作为权威来源和图表作为副产品。但是,如果产出充满了不太符合工作流程中通常理解的“阶段”的相当不直观的“状态”,那么利益相关者沟通的价值就会减少。

这似乎让我(C),给了编辑器一个Submit函数的选项,该函数只包含一堆if语句来确定正确的下一个触发.Fire()。一方面,感觉就像国家机器框架所要提供的优势一样倒退(这对于无国籍者来说并不轻微 - 这个问题的目的是确定我是否持有错误)。另一方面,我认识到我仍然可以通过简单的过渡获得其结构相对于其他状态的好处。

another SO question提供了一个更简单的例子:

  

我们来看一下简单的ATM示例。如果用户按“确认”并且PIN正确,请转到状态2.如果用户按“确认”并且PIN不正确,请转到状态3.

这个问题似乎要求更多关于建模/符号而不是实现,但这个例子类似于编辑器在她完成的表格上按Submit的例子。

TL; DR:

状态机框架应该在哪里/如何确定下一个状态应该是什么?或者,这实际上超出了状态机的范围,状态机实际上只用于跟踪当前状态并验证是否允许请求的转换?

1 个答案:

答案 0 :(得分:0)

作为一个建议,我认为您可以考虑自引用转换在编辑器中是否有用。例如,语法状态将具有可能为空或非空的标记错误的内部列表。不会发生转换,但您可以将其视为向当前状态的无限转换。语法状态的转换发生在触发事件(例如提交)之后,此时将测试内部列表以确定下一个状态。