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

Rya*_*ubi 5 c# state-machine stateless-state-machine

长话短说:

\n\n

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

\n\n
\n\n

背景和细节:

\n\n

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

\n\n
\xe2\x94\x8c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xac\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x90\n\xe2\x94\x82 W \xe2\x94\x82    \xe2\x94\x8c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x90                         \xe2\x94\x82\n\xe2\x94\x82 r \xe2\x94\x82    \xe2\x94\x82           \xe2\x94\x82                         \xe2\x94\x82\n\xe2\x94\x82 i \xe2\x94\x82    \xe2\x94\x82   Write   \xe2\x97\x84\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x90                \xe2\x94\x82\n\xe2\x94\x82 t \xe2\x94\x82    \xe2\x94\x82           \xe2\x94\x82        \xe2\x94\x82                \xe2\x94\x82\n\xe2\x94\x82 e \xe2\x94\x82    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x98        \xe2\x94\x82                \xe2\x94\x82\n\xe2\x94\x82 r \xe2\x94\x82          \xe2\x94\x82              \xe2\x94\x82                \xe2\x94\x82\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80Submit\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x82\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xa4\n\xe2\x94\x82   \xe2\x94\x82          \xe2\x94\x82              \xe2\x94\x82                \xe2\x94\x82\n\xe2\x94\x82   \xe2\x94\x82    \xe2\x94\x8c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x96\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x90        \xe2\x94\x82                \xe2\x94\x82\n\xe2\x94\x82   \xe2\x94\x82    \xe2\x94\x82           \xe2\x94\x82        \xe2\x94\x82                \xe2\x94\x82\n\xe2\x94\x82   \xe2\x94\x82    \xe2\x94\x82  Review   \xe2\x97\x84\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xac\xe2\x94\x80\xe2\x94\x82\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x90     \xe2\x94\x82\n\xe2\x94\x82   \xe2\x94\x82    \xe2\x94\x82           \xe2\x94\x82      \xe2\x94\x82 \xe2\x94\x82          \xe2\x94\x82     \xe2\x94\x82\n\xe2\x94\x82   \xe2\x94\x82    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x98      \xe2\x94\x82 \xe2\x94\x82          \xe2\x94\x82     \xe2\x94\x82\n\xe2\x94\x82   \xe2\x94\x82          \xe2\x94\x82            \xe2\x94\x82 \xe2\x94\x82          \xe2\x94\x82     \xe2\x94\x82\n\xe2\x94\x82   \xe2\x94\x82      ____\xe2\x96\xbc___         \xe2\x94\x82 \xe2\x94\x82          \xe2\x94\x82     \xe2\x94\x82\n\xe2\x94\x82 E \xe2\x94\x82     /        \\        \xe2\x94\x82 \xe2\x94\x82          \xe2\x94\x82     \xe2\x94\x82\n\xe2\x94\x82 d \xe2\x94\x82    /  Grammar \\\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80No\xe2\x94\x80\xe2\x94\x80\xe2\x94\x82\xe2\x94\x80\xe2\x94\x98          \xe2\x94\x82     \xe2\x94\x82\n\xe2\x94\x82 i \xe2\x94\x82    \\    OK?   /       \xe2\x94\x82            \xe2\x94\x82     \xe2\x94\x82\n\xe2\x94\x82 t \xe2\x94\x82     \\________/        \xe2\x94\x82         Resolve  \xe2\x94\x82\n\xe2\x94\x82 o \xe2\x94\x82          \xe2\x94\x82           Date          \xe2\x94\x82     \xe2\x94\x82\n\xe2\x94\x82 r \xe2\x94\x82         Yes         Passed         \xe2\x94\x82     \xe2\x94\x82\n\xe2\x94\x82   \xe2\x94\x82          \xe2\x94\x82            \xe2\x94\x82            \xe2\x94\x82     \xe2\x94\x82\n\xe2\x94\x82   \xe2\x94\x82      ____\xe2\x96\xbc___         \xe2\x94\x82            \xe2\x94\x82     \xe2\x94\x82\n\xe2\x94\x82   \xe2\x94\x82     /        \\        \xe2\x94\x82            \xe2\x94\x82     \xe2\x94\x82\n\xe2\x94\x82   \xe2\x94\x82    /   Libel  \\\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80Yes\xe2\x94\x82\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x90   \xe2\x94\x82     \xe2\x94\x82\n\xe2\x94\x82   \xe2\x94\x82    \\   Risk?  /       \xe2\x94\x82        \xe2\x94\x82   \xe2\x94\x82     \xe2\x94\x82\n\xe2\x94\x82   \xe2\x94\x82     \\________/        \xe2\x94\x82        \xe2\x94\x82   \xe2\x94\x82     \xe2\x94\x82\n\xe2\x94\x82   \xe2\x94\x82          \xe2\x94\x82        \xe2\x94\x8c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x82\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x90    \xe2\x94\x82   \xe2\x94\x82     \xe2\x94\x82\n\xe2\x94\x82   \xe2\x94\x82          No       \xe2\x94\x82 Defer \xe2\x94\x82    \xe2\x94\x82   \xe2\x94\x82     \xe2\x94\x82\n\xe2\x94\x82   \xe2\x94\x82          \xe2\x94\x82        \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x96\xb2\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x98    \xe2\x94\x82   \xe2\x94\x82     \xe2\x94\x82\n\xe2\x94\x82   \xe2\x94\x82      ____\xe2\x96\xbc___         \xe2\x94\x82        \xe2\x94\x82   \xe2\x94\x82     \xe2\x94\x82\n\xe2\x94\x82   \xe2\x94\x82     /        \\        \xe2\x94\x82        \xe2\x94\x82   \xe2\x94\x82     \xe2\x94\x82\n\xe2\x94\x82   \xe2\x94\x82    / Embargo? \\\xe2\x94\x80Yes\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x98        \xe2\x94\x82   \xe2\x94\x82     \xe2\x94\x82\n\xe2\x94\x82   \xe2\x94\x82    \\          /                \xe2\x94\x82   \xe2\x94\x82     \xe2\x94\x82\n\xe2\x94\x82   \xe2\x94\x82     \\________/                 \xe2\x94\x82   \xe2\x94\x82     \xe2\x94\x82\n\xe2\x94\x82   \xe2\x94\x82          \xe2\x94\x82                     \xe2\x94\x82   \xe2\x94\x82     \xe2\x94\x82\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80No\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x82\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x82\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xa4\n\xe2\x94\x82 L \xe2\x94\x82          \xe2\x94\x82                     \xe2\x94\x82   \xe2\x94\x82     \xe2\x94\x82\n\xe2\x94\x82 e \xe2\x94\x82          \xe2\x94\x82               \xe2\x94\x8c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x96\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x82\xe2\x94\x80\xe2\x94\x90   \xe2\x94\x82\n\xe2\x94\x82 g \xe2\x94\x82          \xe2\x94\x82               \xe2\x94\x82   Legal   \xe2\x94\x82   \xe2\x94\x82\n\xe2\x94\x82 a \xe2\x94\x82          \xe2\x94\x82               \xe2\x94\x82  Review   \xe2\x94\x82   \xe2\x94\x82\n\xe2\x94\x82 l \xe2\x94\x82          \xe2\x94\x82               \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x98   \xe2\x94\x82\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x82\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xa4\n\xe2\x94\x82 P \xe2\x94\x82          \xe2\x94\x82                               \xe2\x94\x82\n\xe2\x94\x82 r \xe2\x94\x82    \xe2\x94\x8c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x96\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x90                       \xe2\x94\x82\n\xe2\x94\x82 i \xe2\x94\x82    \xe2\x94\x82             \xe2\x94\x82                       \xe2\x94\x82\n\xe2\x94\x82 n \xe2\x94\x82    \xe2\x94\x82  Print it!  \xe2\x94\x82                       \xe2\x94\x82\n\xe2\x94\x82 t \xe2\x94\x82    \xe2\x94\x82             \xe2\x94\x82                       \xe2\x94\x82\n\xe2\x94\x82 e \xe2\x94\x82    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x98                       \xe2\x94\x82\n\xe2\x94\x82 r \xe2\x94\x82                                          \xe2\x94\x82\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x98\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

实现这一点的一种方法 (A)是让用户有责任选择适当的转换;因此在这种情况下,编辑器将有单独的按钮,称为Revert to Check SpellingRefer for Legal ReviewDefer Publication。这些将连接到Article对象上的相应方法,这些方法根据推荐的方法.Fire(...)在内部调用_stateMachine相应的方法。Triggers

\n\n

然而,这至少有两个缺点。首先,它增加了用户的认知负担(在本例中是轻微增加的,但为了这个例子,请继续听我说)。她不应该选择要做什么她应该能够一次性完成所有数据输入,如下所示:

\n\n
\xe2\x94\x8c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xac\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x90\n\xe2\x94\x82 Spelling OK?    \xe2\x94\x82 Yes [ ]   No [ ]     \xe2\x94\x82\n\xe2\x94\x82 Libel Risk?     \xe2\x94\x82 Yes [ ]   No [ ]     \xe2\x94\x82\n\xe2\x94\x82 Embargo?        \xe2\x94\x82 Date [ dd/mm/yyyy ]  \xe2\x94\x82\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x98\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后应用程序应该决定做什么。这也将防止用户做出错误的选择:回答有关内容的事实问题比考虑到可能存在的许多输入(想象一个更复杂的示例)来决定正确的行动方案更容易。

\n\n

第二个缺点是审阅可能会过早中断:每当发现一个问题并触发相应的操作时,编辑就无法继续审阅以可能发现其他问题。一旦第一个问题得到解决,文章再次返回审查,实际上又从头开始。

\n\n

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

\n\n

此外,这感觉就像远离我们相对干净的世界模型,或者至少远离状态机库提供的所谓的清洁度。想象一下在更复杂的示例中状态的扩散,用户输入更多数量的变量。我期待使用无状态导出到 DOT 图功能来实现,正如他们所说,代码作为权威来源,图表作为副产品。然而,如果输出充满了相当不直观的“状态”,这些“状态”不再对应于通常理解的工作流程“阶段”,那么利益相关者沟通的价值就会减少。

\n\n

这似乎给我留下了(C),即为编辑器提供一个Submit函数的选项,该函数仅包含一堆if语句来确定 的正确下一个触发器.Fire()。一方面,这感觉像是从状态机框架应提供的优势中倒退了(这对 Stateless\xe2\x80\x94 来说并不是轻视,这个问题的目的是确定我是否持有错误的观点) 。另一方面,我认识到我仍然受益于其结构相对于其他状态的好处,并且转换更简单。

\n\n
\n\n

还有另一个 SO 问题提供了一个更简单的示例:

\n\n
\n

让我们以简单的 ATM 为例。如果用户按“确认”且 PIN 正确,则转至状态 2。如果用户按“确认”且 PIN 不正确,则转至状态 3。

\n
\n\n

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

\n