【问题标题】:How would you implement a Workflow system?您将如何实施工作流系统?
【发布时间】:2012-04-19 10:15:30
【问题描述】:

我需要实现一个工作流系统。

例如,要导出一些数据,我需要:

  1. 使用 XSLT 处理器转换 XML 文件
  2. 使用生成的转换转换为任意数据结构
  3. 使用结果(文件或数据)并生成存档
  4. 将存档移动到给定文件夹中。

我开始创建两种类型的类,Workflow,它负责添加新的 Step 对象并运行它。

每个步骤都实现一个 StepInterface。

我主要担心的是我的所有步骤都依赖于前一个步骤(第一个除外),我想知道处理此类问题的最佳方法是什么。

我想遍历每个步骤并为每个步骤提供前一个步骤的结果(如果有的话),但我对此并不满意。

另一个想法是允许将“上一个”步骤设置为步骤,例如:

$s = new Step();
$s->setPreviousStep(Step $step);

但我失去了工作流类的实用性。

有什么想法、建议吗?

顺便说一句,我也关心整个工作流程的成败,这意味着如果任何步骤失败,我需要回滚或清理以前的数据。

【问题讨论】:

    标签: algorithm oop workflow


    【解决方案1】:

    去年我实现了一个类似的工作流引擎(虽然是封闭源代码 - 所以没有我可以分享的代码)。以下是基于该经验的一些想法:

    1. StepInterface - 可以做你现在正在做的事情 - 抽象一个步骤。
    2. 此外,提供回滚功能,但我认为一个步骤应该知道它何时失败并在继续之前进行清理。一个抽象的步骤可以为你处理这个(模板方法)
    3. 您可能需要考虑基于 StepResult 进行分支 - 因此您可以执行一个 StepMatcher ,它接受一个 stepResult 对象和一个条件 - 只有当条件返回 true 时才会执行其子步骤。
    4. 如果步骤出错,您还可以执行 StepException 来处理异常流。理想情况下,您可以在工作流级别(如果任何步骤失败时执行此操作)和/或在步骤级别定义。
    5. 我采用的方法是,一个步骤返回一个可用于下一步的明确定义的结构 (StepResult)。如果有大量数据(比如大文件等),则资源的 URI/定位器会在 StepResult 中传递。
    6. 您的工作流将需要一个上下文来使用 - 在您引用的示例中,这将是文件的名称、存档的位置等等 - 所以想想 WorkflowContext
    额外的想法

    您可能还需要考虑以下事项 - 如果您打算将其作为大型服务/服务器实施:

    1. 步骤可能在动态加载的库中
    2. XML/JSON 文件中的工作流定义 - 同样,在编辑时会动态重新加载。
    3. 远程调用和回调 - 使用回调 API 将作业提交到远程服务。当远程服务回调时,将在流程的后续步骤中执行工作流。
    4. 尽可能并行执行等
    5. 无状态设计

    【讨论】:

      【解决方案2】:

      回滚可以很容易地适应这种结构,因为每个Step 将实现自己的rollback() 方法,如果任何步骤失败,工作流可以调用(最好以相反的顺序)。

      至于主要问题,这实际上取决于您想要获得的复杂程度。在基本层面上,您可以定义一个StepResult 接口,该接口由每个步骤返回并传递到下一个步骤。这种方法的明显问题是每一步都应该“知道”StepResult 的哪个实现。对于小型系统,这可能是可以接受的,对于大型系统,您可能需要某种可配置的映射框架,该框架可以被告知如何将上一步的结果转换为下一步的输入。所以Workflow 将调用StepStep 返回StepResultWorkflow 然后调用StepResultConverter(这是你的可配置映射的东西),StepResultConverter 返回一个StepInputWorkflow 然后调用下一个 StepStepInput 等等。

      【讨论】:

      • 嗨,感谢您的宝贵回答,我做了类似的事情(至少第一步,pastebin.com/KF2bp0Wy)我也有一个 StepResult 但不是 StepInput,关于“配置”,因为我正在使用 Symfony2 我想使用 ConfigurationBuilder 来验证结果。
      • 恐怕我不能给你任何实现帮助,除非你是用Java做的。 :) 请注意,执行回滚的“自然”方式是以相反的顺序调用它们,以便每个步骤都可以知道它处于与运行后完全相同的状态。
      【解决方案3】:

      我在使用finite state machine 实施工作流程方面取得了巨大成功。它可以像您喜欢的那样简单或复杂,多个工作流程相互链接。通常,FSM 可以实现为一个简单的表,其中通过保存对象上的转换日志并简单地检索最后一个条目,在历史表中跟踪给定对象的当前状态。所以转换的形式是:

      nextState = TransLookup(currState, Event, [条件])

      如果您正在实现前端,则可以使用此转换信息来构造一个可用于当前状态的给定对象的事件列表。

      【讨论】:

        猜你喜欢
        • 2012-12-13
        • 2011-09-12
        • 2013-02-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-20
        • 2010-10-06
        • 2018-09-24
        相关资源
        最近更新 更多