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

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

  1. 备用
  2. 安装
  3. 在维修

物品可能在每个州花费数月,并且有数千种物品。

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

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

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

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

谢谢!

更新:

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

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

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

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

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

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

  • 破碎并安装
  • 破碎并更换
  • 在商店进行维修
  • 修复
  • 等等

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

这是一个示例状态机:

var phoneCall = new StateMachine(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( () => myState.Value, s => myState.Value = s); 

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

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

  1. 将每个项目的状态存储在项目本身中。
    这可以非常容易地实现:将一个成员添加到一个类或一个列到一个表等,就像其他post/评论中已经提到的那样。
  2. 使用一个状态机(这可以是从类的实例到具有合法转换的表的任何内容),它保存您的业务逻辑,即状态之间允许的转换以及有关在项目时执行哪些其他操作的知识改变它的状态。

您需要做的就是使用状态机转换您的项目,每当发生extern事件时,强制/暗示这一点。

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

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

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

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

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

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

希望有帮助!

正如对原始post的评论中所讨论的,我对使用WF完全解决这个问题存在一些问题。

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

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

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

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

当州政府推动业务或需要一个受信任的单一代码时,状态机是有意义的,而这些代码是负责“有效转换”的唯一参与者。

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

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

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

我想我们需要在这里了解一些事情。

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

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

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

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

关键在于您必须以实体的状态转换之间的方式定义scxml – 您可以使用“actions”或“listeners”指定要执行的工作流。

示例程序: 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