“思考得少,瞎干得多”,就是目前企业开发的现状。瞎干了两个月后,回头来分析一下一个有趣的流程,是我们目前项目中最复杂的一个流程(因为要完成它而不能动脑,所以复杂)。
首先把UML书上的案例扔到一边,那个是齐全的菜谱、佐料、原料而真实项目是荒地。想想走到荒地上给自己整一顿满汉全席,不容易啊……
现在已经忘了最初听到这个流程的描述是怎么样的了。大概就是“一个待办项会发送和接收很多次,也可以发送接收一次,发送完后就不能再次发送了,最后一个接收结束后才能结束整个流程”——够昏的吧^O^遇到这种事千万不能听客户、需求人员甚至项目经理的,架构师才是设计这个系统的人,不能自己分析、定义业务对象,下课去吧。
第一反应就是发送和接收必须是两个不同的待办项,随后是必须定义两个不同的动作:完全发送和部分发送。概念一定要区分准确。
随后关于如何叫完全发送和部分发送有几次需求上的变化,但不影响流程的执行规则。这个就形成了我在业务流程配置一文中写的ResponseTask类,当时的需求就是请求-接收,所以只写了两个Task;随后扩展成了每接收之后还有一个任务叫填写意见书,所有的意见书完成之后再开始一个新的任务。所以就改成了:请求-接收-响应三个操作,修改ResponseTask,增加了ResponseType这一枚举值属性,修改了结束的算法。目前的流程执行规则是相当死板的,完全硬编码在引擎内部,无法改变。以下是ResponseTask类和执行代码:
昨天参考了Workflow Pattern,其实这个被我表达为Request-Receive-Response的流程的标准描述是以下两个的综合:
[u][b]Parallel split pattern[/b][/u]
[img]http://www.workflowpatterns.com/patterns/control/images/fig2.png[/img]
[u][b]Synchronization pattern[/b][/u]
[img]http://www.workflowpatterns.com/patterns/control/images/fig3.png[/img]
于是我拿出纸和笔,画下了这幅图:
[img]http://byfiles.storage.msn.com/y1pYaKuZFHNqghlnFGBbOTxQybyxFGnnmIzUsyMvwaiRpa8jecXCislz7q89ztKKPpG?PARTNER=WRITER[/img]
想了想,这副图没有把完全发送与部分发送的分支表达出来,于是改成了这幅:
[img]http://byfiles.storage.msn.com/y1ptzqXXQRceTSdRHfGIdUplDDAKNjJC4oVUeIs7D6bWLy0T8xsDf8syh9Fxxcxvpbw?PARTNER=WRITER[/img]
现在呢,有了选择。如果用户选择部分发送,它将走图一的流程,否则就一个简单的2-3-4走完。但是,这时依然缺少了东西,缺少了4开始的条件。并且,部分提交和完全提交唯一的区别就是是否结束1,所以不用专门配分支,再把选择和任务2视为并发任务,因为他们没有先后关系,虽然界面上操作有先有后,但这个选择不能决定任务2是否产生。又改:
[img]http://byfiles.storage.msn.com/y1p7fDA7DKWWUofK3I9RFS8ot8OeqM6OiQC4c8aBDG7V-ZvkhQ0xM7rcriNTnuHiO0W?PARTNER=WRITER[/img]
这一个算是比较满意的分析模型。根据这个模型,先前硬编码的执行算法将被抽象为ControlRule,它将继承自RuleBase,代表了上图的流程线。而这个分支是用户在执行时选择的,暂定名为Choice:
规则引擎将解释这个配置并执行。而在Task的执行上,也会定义在配置中,而不是现在这样硬编码。例,选择完全提交之后结束任务一:
这里Mode="auto"意为系统自动处理,不需要产生待办项。接下来是关于任务2的产生,它与Choice并行关系的,而且是任务一提交后必然无条件产生的,故命名为Unconditional:
这里的Mode="manual"表示会生成一条待办项,到达指定办理人处。对于最后任务4启动的验证:
至此,已经基于规则实现了这个流程,其中的三条规则是:选择型、条件型、无条件型;进一步了解之后再进行补充。下一次,将围绕任务进行面向行为的分析,核心问题还是办理人的持久化目的地。
首先把UML书上的案例扔到一边,那个是齐全的菜谱、佐料、原料而真实项目是荒地。想想走到荒地上给自己整一顿满汉全席,不容易啊……
现在已经忘了最初听到这个流程的描述是怎么样的了。大概就是“一个待办项会发送和接收很多次,也可以发送接收一次,发送完后就不能再次发送了,最后一个接收结束后才能结束整个流程”——够昏的吧^O^遇到这种事千万不能听客户、需求人员甚至项目经理的,架构师才是设计这个系统的人,不能自己分析、定义业务对象,下课去吧。
第一反应就是发送和接收必须是两个不同的待办项,随后是必须定义两个不同的动作:完全发送和部分发送。概念一定要区分准确。
随后关于如何叫完全发送和部分发送有几次需求上的变化,但不影响流程的执行规则。这个就形成了我在业务流程配置一文中写的ResponseTask类,当时的需求就是请求-接收,所以只写了两个Task;随后扩展成了每接收之后还有一个任务叫填写意见书,所有的意见书完成之后再开始一个新的任务。所以就改成了:请求-接收-响应三个操作,修改ResponseTask,增加了ResponseType这一枚举值属性,修改了结束的算法。目前的流程执行规则是相当死板的,完全硬编码在引擎内部,无法改变。以下是ResponseTask类和执行代码:
using System;
using System.Collections.Generic;
using System.Xml.Serialization;
namespace Microsoft.Applications.ChinaMobilePMS.FlowEngine
{
public class ResponseTask : TaskBase, IComparable<ResponseTask>
{
private int requestNumber = 0;
private ResponseType responseMode = ResponseType.Request;
[XmlAttribute("RequestNumber")]
public int RequestNumber
{
get { return requestNumber; }
set { requestNumber = value; }
}
[XmlAttribute("Mode")]
public ResponseType ResponseMode
{
get { return responseMode; }
set { responseMode = value; }
}
#region IComparable<ResponseTask> Members
public int CompareTo(ResponseTask other)
{
if (this.responseMode < other.responseMode) { return -1; }
else if (this.responseMode == other.responseMode) { return 0; }
else { return 1; }
}
#endregion
}
}
using System;
using System.Collections.Generic;
using System.Xml.Serialization;
namespace Microsoft.Applications.ChinaMobilePMS.FlowEngine
{
public class Activity : IActivity
{
//...
public void StartActivity(string actionValue)
{
switch (mode)
{
case TaskMode.Response:
{
responseTasks.Sort();
ResponseTask requestTask = responseTasks[0];
ResponseTask receiveTask = responseTasks[1];
ResponseTask responseTask = responseTasks[2];
if (status == StatusType.Scheduled)
{
status = StatusType.InProgress;
requestTask = responseTasks[0];
requestTask.CreateTask();
}
else if (status == StatusType.InProgress)
{
switch (actionValue)
{
case "CompleteSubmit":
requestTask.Approve += new ApproveHandler(receiveTask.CreateTask);
requestTask.ApproveTask();
receiveTask.RequestNumber++;
break;
case "Submit":
receiveTask.CreateTask();
receiveTask.RequestNumber++;
break;
case "Receive":
receiveTask.Approve += new ApproveHandler(responseTask.CreateTask);
receiveTask.ApproveTask();
receiveTask.RequestNumber--;
responseTask.RequestNumber++;
break;
case "Reject":
receiveTask.Reject += new RejectHandler(requestTask.CreateTask);
receiveTask.RejectTask();
receiveTask.RequestNumber--;
break;
case "Response":
responseTask.ApproveTask();
responseTask.RequestNumber--;
if (((requestTask.Status == StatusType.Completed) && (receiveTask.RequestNumber <= 0) && (responseTask.RequestNumber <= 0)))
{
CompleteActivity();
}
else
{
responseTask.Status = StatusType.InProgress;
}
break;
default:
break;
}
}
}
break;
}
}
}
}
昨天参考了Workflow Pattern,其实这个被我表达为Request-Receive-Response的流程的标准描述是以下两个的综合:
[u][b]Parallel split pattern[/b][/u]
[img]http://www.workflowpatterns.com/patterns/control/images/fig2.png[/img]
[u][b]Synchronization pattern[/b][/u]
[img]http://www.workflowpatterns.com/patterns/control/images/fig3.png[/img]
于是我拿出纸和笔,画下了这幅图:
[img]http://byfiles.storage.msn.com/y1pYaKuZFHNqghlnFGBbOTxQybyxFGnnmIzUsyMvwaiRpa8jecXCislz7q89ztKKPpG?PARTNER=WRITER[/img]
想了想,这副图没有把完全发送与部分发送的分支表达出来,于是改成了这幅:
[img]http://byfiles.storage.msn.com/y1ptzqXXQRceTSdRHfGIdUplDDAKNjJC4oVUeIs7D6bWLy0T8xsDf8syh9Fxxcxvpbw?PARTNER=WRITER[/img]
现在呢,有了选择。如果用户选择部分发送,它将走图一的流程,否则就一个简单的2-3-4走完。但是,这时依然缺少了东西,缺少了4开始的条件。并且,部分提交和完全提交唯一的区别就是是否结束1,所以不用专门配分支,再把选择和任务2视为并发任务,因为他们没有先后关系,虽然界面上操作有先有后,但这个选择不能决定任务2是否产生。又改:
[img]http://byfiles.storage.msn.com/y1p7fDA7DKWWUofK3I9RFS8ot8OeqM6OiQC4c8aBDG7V-ZvkhQ0xM7rcriNTnuHiO0W?PARTNER=WRITER[/img]
这一个算是比较满意的分析模型。根据这个模型,先前硬编码的执行算法将被抽象为ControlRule,它将继承自RuleBase,代表了上图的流程线。而这个分支是用户在执行时选择的,暂定名为Choice:
<ControlRule Mode="Choice">
<Choice Result="Complete">
<Then />
</Choice>
<Choice Result="Partial">
<Then />
</Choice>
</ControlRule>
规则引擎将解释这个配置并执行。而在Task的执行上,也会定义在配置中,而不是现在这样硬编码。例,选择完全提交之后结束任务一:
<ControlRule Mode="Choice">
<Choice Result="Complete">
<Then>
<Task ID="1" Action="End" Mode="auto" />
</Then>
</Choice>
</ControlRule>
这里Mode="auto"意为系统自动处理,不需要产生待办项。接下来是关于任务2的产生,它与Choice并行关系的,而且是任务一提交后必然无条件产生的,故命名为Unconditional:
<ControlRule Mode="Choice" />
<ControlRule Mode="Unconditional">
<Task ID="2" Action="Start" Mode="manual" />
</ControlRule>
这里的Mode="manual"表示会生成一条待办项,到达指定办理人处。对于最后任务4启动的验证:
<ControlRule Mode="Conditional">
<Condition>
<Task ID="1" Status="Completed" />
<Task ID="2" Status="Completed" />
<Task ID="3" Status="Completed" />
</Condition>
<Then>
<Task ID="4" Action="Start" Mode="manual" />
</Then>
</ControlRule>
至此,已经基于规则实现了这个流程,其中的三条规则是:选择型、条件型、无条件型;进一步了解之后再进行补充。下一次,将围绕任务进行面向行为的分析,核心问题还是办理人的持久化目的地。