2012-04-05 59 views
1

我需要实现一个工作流程系统。您将如何实施Workflow系统?

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

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

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

每个步骤实现一个StepInterface。

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

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

另一个想法已经允许“前面的”步骤被设定于一个步骤,如:

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

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

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

回答

1

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

至于主要问题,这取决于你想得到多么复杂。在基本级别上,您可以定义一个StepResult接口,每个步骤返回并传递到下一个接口。这种方法的明显问题是每一步都应该“知道”StepResult的期望执行。对于小型系统来说,这可能是可以接受的,对于大型系统,您可能需要某种可配置的映射框架,可以告诉如何将上一步的结果转换为下一步的输入。所以Workflow将调用StepStep回报StepResultWorkflow然后调用StepResultConverter(这是你的配置映射啄),StepResultConverter返回StepInputWorkflow然后调用下一StepStepInput等。

+0

您好,感谢您的宝贵答案,我做了类似的事情(至少是第一步,http://pastebin.com/KF2bp0Wy)我虽然过的StepResult但不是StepInput,关于“配置”为我正在使用Symfony2我想知道如何使用ConfigurationBuilder来验证结果。 – Trent 2012-04-05 18:19:42

+0

恐怕我不能给你任何实施帮助,除非你用Java来做。 :)请注意,回滚的“自然”方法是以相反顺序调用它们,以便每个步骤都可以知道它处于与运行后完全相同的状态。 – biziclop 2012-04-05 18:32:23

3

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

  1. StepInterface - 可以做你现在正在做的事情 - 抽象一步。
  2. 此外,提供回滚的能力,但我认为,当它失败了一步应该知道和进一步处理之前进行清理。一个抽象的步骤可帮助您处理该(模板方法)
  3. 你可能要考虑基础上,StepResult分支 - 这样你就可以做一个StepMatcher,需要一个stepResult对象和条件 - 其子步骤,如果只执行条件返回true。
  4. 你也可以做一个StepException处理例外流程。如果某个步骤出现了错误。理想情况下,您可以在工作流级别进行定义(如果任何步骤失败,请执行此操作)和/或在步骤级别进行定义。
  5. 我已经采取了一步返回所有可用的下一个步骤一个定义良好的结构(StepResult)的方法。如果存在庞大的数据(比如大文件等),那么资源的URI /定位器将在StepResult中传递。
  6. 您的工作流程将需要上下文一起工作 - 在你引用的例子,这将是该文件的名称,归档等的位置 - 这样认为WorkflowContext
附加的思想

你可能要考虑以下几点太 - 如果这是什么,你打算实施的大规模服务/服务器:

  1. 步骤可以在图书馆进行动态加载的
  2. 工作流程定义在XML/JSON文件中 - 再次在编辑时动态重新加载。
  3. 远程调用和回调 - 作业提交给远程服务,回调API。当远程服务回调时,流程中的后续步骤会执行工作流程执行。
  4. 并行执行在可能的情况等
  5. 无国籍设计
1

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

nextState = TransLookup(currState,事件,[状态])

如果要实现前端您可以使用此转换信息来构建可在事件列表到当前状态下的给定对象。