2

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

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

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

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

每个 Steps 实现一个 StepInterface。

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

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

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

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

但是我失去了 Workflow 类的实用性。

有什么想法、建议吗?

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

4

3 回答 3

4

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

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

您可能还需要考虑以下内容 - 如果这是您计划作为大规模服务/服务器实施的内容:

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

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

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

于 2012-04-05T18:00:38.903 回答
1

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

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

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

于 2015-09-29T19:30:18.080 回答