通用流程管理要做些什么
通用流程管理旨在抽象出流程部分,让流程与业务进行松耦合,那么这个抽象过程就需要考虑出完整的结构,以适合尽可能多的业务。
我们通常做项目的时候,都把业务流程两个词儿放到一起考虑,其实我们不妨把业务和流程分开考虑。当业务和流程分开之后,可以想象,业务层就可以减轻大量的工作。
当然,随之而来的要求就是需要我们通用流程部分不断去迭代。以兼容更多的业务流程情形。
基础的结构
首先,我们还是按照一个有向无环图的理论点去推进。那么整个流程就可以抽象成以下几个点:
- 流程图
- 流程节点
- 流程边
首先,流程图就是描述整个流程的情况,初步实验的结构如下
public class ProcessTree {
private ProcessNode beginNode;
private String processName;
private Long processId;
private String processDesc;
}
流程节点,就是每个流程的顶点,结构如下
public class ProcessNode {
private Long nodeId; // 节点标识
private String processName; // 节点名
private String nodeType; // 节点类型
private Boolean processStart; // 起始节点
private Boolean processFinish; // 结束节点
private String processStatus; // 节点状态
private List<ProcessSide> adjSide; // 邻接边:定义出节点关系
}
流程边,也就是流程节点间的流转关系,结构如下:
public class ProcessSide {
private String relationType; // 关系类型
private ProcessNode toNode; // 达到节点
}
理论上讲,我们的流程节点应该要挂到某个应用场景下,流程边应该是要控制流转是否可达,但是这里又会存在粒度问题,即流程边是否能与我们的业务挂钩,如果挂钩了,是否显得过于复杂,同时又和松耦合的理念相悖?
测试基础结构的可用性
现在,我定义一个子类来继承ProcessTree,用来表示是某个业务场景下的流程。
package com.chaojilaji.autocli.process.demo;
import com.chaojilaji.autocli.process.ProcessTree;
public class CcsProcessTree extends ProcessTree {
private Long projectId;
private Long bizSystemId;
public CcsProcessTree() {
}
public CcsProcessTree(String processName, Long processId, String processDesc) {
super(processName, processId, processDesc);
}
}
然后,在单元测试里面对以上结构的可序列化和反序列化特性进行初步测试
@Test
public void demo() {
CcsProcessTree processTree = new CcsProcessTree("demo",1L,"demodemodemo");
processTree.setBizSystemId(123L);
processTree.setProjectId(456L);
ProcessNode begin = new ProcessNode(1L,"开始","1",true,false);
processTree.setBeginNode(begin);
ProcessNode a = new ProcessNode(2L,"a","1",false,false);
ProcessSide s1 = new ProcessSide("1",a);
begin.getAdjSide().add(s1);
ProcessNode a1 = new ProcessNode(3L,"a1","1",false,false);
ProcessNode a2 = new ProcessNode(4L,"a2","1",false,false);
ProcessNode a3 = new ProcessNode(5L,"a3","1",false,false);
ProcessSide s2 = new ProcessSide("1",a1);
ProcessSide s3 = new ProcessSide("1",a2);
ProcessSide s4 = new ProcessSide("1",a3);
a.getAdjSide().add(s2);
a.getAdjSide().add(s3);
a.getAdjSide().add(s4);
ProcessNode a11 = new ProcessNode(31L,"a11","1",false,false);
ProcessNode a21 = new ProcessNode(41L,"a21","1",false,false);
ProcessNode a31 = new ProcessNode(51L,"a31","1",false,false);
ProcessSide s5 = new ProcessSide("1",a11);
ProcessSide s6 = new ProcessSide("1",a21);
ProcessSide s7 = new ProcessSide("1",a31);
a1.getAdjSide().add(s5);
a2.getAdjSide().add(s6);
a3.getAdjSide().add(s7);
ProcessNode a111 = new ProcessNode(311L,"a111","1",false,false);
ProcessNode a211 = new ProcessNode(411L,"a211","1",false,false);
ProcessSide s8 = new ProcessSide("1",a111);
ProcessSide s9 = new ProcessSide("1",a211);
a11.getAdjSide().add(s8);
a21.getAdjSide().add(s9);
a31.getAdjSide().add(s9);
ProcessNode a1111 = new ProcessNode(3111L,"a1111","1",false,true);
ProcessSide s10 = new ProcessSide("1",a1111);
a211.getAdjSide().add(s10);
a111.getAdjSide().add(s10);
System.out.println(Json.toJson(processTree));
}
测试的结果,打印出这个流程如下:
{
"begin_node": {
"node_id": 1,
"process_name": "开始",
"node_type": "1",
"process_start": true,
"process_finish": false,
"process_status": "not begin",
"adj_side": [
{
"relation_type": "1",
"to_node": {
"node_id": 2,
"process_name": "a",
"node_type": "1",
"process_start": false,
"process_finish": false,
"process_status": "not begin",
"adj_side": [
{
"relation_type": "1",
"to_node": {
"node_id": 3,
"process_name": "a1",
"node_type": "1",
"process_start": false,
"process_finish": false,
"process_status": "not begin",
"adj_side": [
{
"relation_type": "1",
"to_node": {
"node_id": 31,
"process_name": "a11",
"node_type": "1",
"process_start": false,
"process_finish": false,
"process_status": "not begin",
"adj_side": [
{
"relation_type": "1",
"to_node": {
"node_id": 311,
"process_name": "a111",
"node_type": "1",
"process_start": false,
"process_finish": false,
"process_status": "not begin",
"adj_side": [
{
"relation_type": "1",
"to_node": {
"node_id": 3111,
"process_name": "a1111",
"node_type": "1",
"process_start": false,
"process_finish": true,
"process_status": "not begin",
"adj_side": []
}
}
]
}
}
]
}
}
]
}
},
{
"relation_type": "1",
"to_node": {
"node_id": 4,
"process_name": "a2",
"node_type": "1",
"process_start": false,
"process_finish": false,
"process_status": "not begin",
"adj_side": [
{
"relation_type": "1",
"to_node": {
"node_id": 41,
"process_name": "a21",
"node_type": "1",
"process_start": false,
"process_finish": false,
"process_status": "not begin",
"adj_side": [
{
"relation_type": "1",
"to_node": {
"node_id": 411,
"process_name": "a211",
"node_type": "1",
"process_start": false,
"process_finish": false,
"process_status": "not begin",
"adj_side": [
{
"relation_type": "1",
"to_node": {
"node_id": 3111,
"process_name": "a1111",
"node_type": "1",
"process_start": false,
"process_finish": true,
"process_status": "not begin",
"adj_side": []
}
}
]
}
}
]
}
}
]
}
},
{
"relation_type": "1",
"to_node": {
"node_id": 5,
"process_name": "a3",
"node_type": "1",
"process_start": false,
"process_finish": false,
"process_status": "not begin",
"adj_side": [
{
"relation_type": "1",
"to_node": {
"node_id": 51,
"process_name": "a31",
"node_type": "1",
"process_start": false,
"process_finish": false,
"process_status": "not begin",
"adj_side": [
{
"relation_type": "1",
"to_node": {
"node_id": 411,
"process_name": "a211",
"node_type": "1",
"process_start": false,
"process_finish": false,
"process_status": "not begin",
"adj_side": [
{
"relation_type": "1",
"to_node": {
"node_id": 3111,
"process_name": "a1111",
"node_type": "1",
"process_start": false,
"process_finish": true,
"process_status": "not begin",
"adj_side": []
}
}
]
}
}
]
}
}
]
}
}
]
}
}
]
},
"process_name": "demo",
"process_id": 1,
"process_desc": "demodemodemo",
"project_id": 456,
"biz_system_id": 123
}
证明结构是可用的。更完整的流程抽象,只需要在实施阶段想明白,实现完即可。