工作流设计困境 - 状态机,是或否

时间:2009-12-27 20:29:27

标签: c# .net workflow workflow-foundation

我是WF的初学者,但我读了一本书并做了很多谷歌搜索。我想写一个库存管理服务。库存由具有以下状态的单个项目组成:

  1. 备用
  2. 安装的
  3. 在修复
  4. 物品可能在每个州花费数月,而且有数千种物品。

    问题是,我是否为所有不同的状态创建状态机工作流程?或者我是否创建了在州之间转换的工作流程?

    如果我理解正确,如果我创建单个状态机工作流程,那么将始终为每个项目运行工作流程。这意味着数千个不断运行的工作流程。此外,我需要能够显示每个项目状态的快照,这意味着我必须以某种方式查询它们当前所处状态的所有工作流程,或者在每次状态转换后以其他方式持久保存到数据库。“ p>

    然而,状态机工作流在逻辑上听起来是正确的事情,因此我的困境。

    如果可以,请帮助我: - )

    谢谢!

    更新

    假设我有比上面3更多的状态,并且不是所有的状态转换都是可能的。

    Bounty Winner:Maurice - 感谢其他所有人真正帮助我了解更多有关工作流程,MS工作流程基础以及其他更轻量级的替代方案。不幸的是,只有一个赏金赢家,莫里斯的回答及其评论对我帮助最大。

9 个答案:

答案 0 :(得分:21)

状态机是一种非常强大的实现技术,虽然我建议您考虑一个名为StateLess by Nicholas Blumhardt (Autofaq creator)的框架,因为它是一个非常简单的状态机实现,可以避免不必要的Windows Workflow复杂性。他的方法避免了运行时引擎持有的长时间运行工作流的问题,因为状态是由一个简单的变量(如字符串或int)定义的。

这是一个示例状态机:

var phoneCall = new StateMachine<State, Trigger>(State.OffHook);

phoneCall.Configure(State.OffHook)
    .Permit(Trigger.CallDialed, State.Ringing);

phoneCall.Configure(State.Ringing)
    .Permit(Trigger.HungUp, State.OffHook)
    .Permit(Trigger.CallConnected, State.Connected);

phoneCall.Configure(State.Connected)
    .OnEntry(() => StartCallTimer())
    .OnExit(() => StopCallTimer())
    .Permit(Trigger.LeftMessage, State.OffHook)
    .Permit(Trigger.HungUp, State.OffHook)
    .Permit(Trigger.PlacedOnHold, State.OnHold);

// ...

phoneCall.Fire(Trigger.CallDialled);
Assert.AreEqual(State.Ringing, phoneCall.State);

您的状态可以是一个整数,允许您从数据库中提取当前状态。这可以在状态机的构造函数上设置如下:

var stateMachine = new StateMachine<State, Trigger>(
    () => myState.Value,
    s => myState.Value = s);

与运行Windows Workflow所需的多个项目相比,您只需在一个程序集中实现此功能。维护是非常低的,他们不是为你的代码生成代码的“设计师”。再次,它很简单,并且有美丽。

答案 1 :(得分:9)

不确定工作流程是否符合您的要求。

工作流是某种发生的业务流程。这意味着该过程的开始和结束。您的说明听起来更像是跟踪库存中包含物品的库存。

当项目更改状态时,工作流声音更合适。例如,当一个项目被安装并且发生故障并且需要修复时,您将启动一个工作流程以将部件替换为工作部件,将损坏的部件发送到固定部分,最后将其作为固定部件返回仓库。备用。工作流程将描述此过程,并从项目被破坏的报告开始,并以修复或丢弃和替换项目结束。

这个最后的工作流很可能是一个状态工作流,因为该项目经历了各个阶段,如:

  • 破碎并安装
  • 破碎并更换
  • 在维修店
  • 修复

答案 2 :(得分:2)

鉴于您的添加(超过3个状态,并非所有转换都被允许),我会执行以下操作:

  1. 将每个项目的状态存储在项目本身中。
    这可以非常轻松地实现:将一个成员添加到一个类或一个列到一个表等,就像其他帖子/评论中已经提到的那样。
  2. 使用一个状态机(这可以是从类的实例到具有合法转换的表的任何内容),它保存您的业务逻辑,即状态之间允许的转换以及有关要执行的其他操作的知识,当一个项目改变其状态时。
  3. 然后,您需要做的就是使用状态机转换您的项目,无论何时发生extern事件,强制/暗示这一点。

答案 3 :(得分:2)

确定。让我们看看我是否可以帮助你。让我们从设计开始:

设计状态机和工作流是有意义的。两者都只是对你的问题有不同的看法,并从不同的角度阐述了它。实际上,经常发生的情况是,工作流程新手的开发人员设计状态机而不是工作流程。工作流程过程视图主要切换图中框和转换的角色:框是一个可以改变状态的活动 - 在转换时,工作项可以进入一个新状态(好吧,这不是科学上正确的,但它可能会有所帮助: - )

对我来说,似乎国家机器方面更重要。因此,将您的软件实现为状态机。

是的 - 你应该让所有项目都在数据库中持久化。这就是你如何运行长时间运行的工作流程 - 它们存在于数据库中,直到它们被任何活动重新激活。这就是搁置业务流程管理系统(BPMS)所做的一切。这些工作流程不会保留在内存中。

将所有内容保存在数据库中可以轻松创建报告。

正如其他人已经提到的那样,创建一个包含状态信息的新列,甚至创建一个包含元数据的新表:状态,可能是状态发生变化时的日志,更改状态的人,有关即将发生的事件的信息(部分已订购但未交付 - 如果交货已丢失,有人需要与供应商核实多少天?)。这将使您有机会根据需要添加元数据,而不会影响您的零件数据库。

希望有帮助!

答案 4 :(得分:1)

正如对原始帖子的评论中所讨论的,我在使用WF时遇到了一些问题。

句子“项目可能在每个州花费数月,并且有数千项”是触发器:我相信工作流程(使用WF建模)应该更短。虽然WF实例可以或应该存在多长时间没有硬性规则,但是几个月甚至几年都会引发我的“越界”异常,特别是当这种情况非常普遍时成千上万的物品: - )

在评论中使用WF的原因是合理的,但不解决这一点。因此,我建议您使用较短寿命的专用WF模型来处理库存项目状态之间发生的事情,但不要在WF状态下捕获项目状态本身。长期存在,很少改变的状态更适合数据库引擎,人们期望它们在那里容易报告。

答案 5 :(得分:0)

即使状态机模式在技术上是正确的选项,也可以选择使用一个巨型循环创建顺序工作流。在某些情况下,它实际上更好,更容易理解。

答案 6 :(得分:0)

您有三种不同的状态,据我所知,所有过渡都是允许的。鉴于此,我不打算在一段代码意义上检查允许的转换并继续前进的状态机。

状态机在国家推动业务或需要一个可靠的单一代码时是有意义的,而这些代码是负责“验证过渡”的唯一参与者。

更简单地说,你只需要在任何时间点具有给定状态的实体......

答案 7 :(得分:0)

Aviad,我同意你的意见,即工作流程应该在州之间。清点零件的状态听起来像是物品的状态/属性。该状态几乎可以以任何方式存储(例如数据库,文件......),因为状态之间的项目移动将存在于业务逻辑层中。

听起来像一个有趣的项目,祝你好运。

答案 8 :(得分:0)

我认为我们需要了解一些事情。

状态机 - 将专注于代表您的实体所处的特定州。

WorkFlow - 将定义您将实体从初始状态移动到最终状态所遵循的流程。

在您的情况下,由于您的整个流程围绕单个实体展开,并且其在任何给定时间点的当前状态是单例,我建议您使用状态机。

<强>建议: Apache Commons SCXML提供了一个轻量级,可嵌入的状态机引擎,可以在应用程序的运行时轻松配置和自定义。

这里的关键点是你必须以实体的状态转换之间的方式定义你的scxml - 你可以使用&#39; actions&#39;来指定你想要执行的工作流程。或者&#39;听众&#39;。

示例程序: https://www.javacodegeeks.com/2012/06/apache-commons-scxml-finite-state.html

更多关于Commons SCXML 2.0 https://events.linuxfoundation.org/sites/events/files/slides/ApacheConUS2014%20-%20Apache%20Commons%20SCXML%202.0.pdf