工作流概念
2016-05-05 14:44
288 查看
工作流。真正实施时应多看网上的例子,或开源项目。由于时间关系这里只记下我的一些基础想法。
一个项目可以有多个工作流,对应多个工作。例如下订单流程、申请审核转正流程。
一个业务应该对应一个流程,如果它有多种情况,应该多设置节点和路径即可。如果将同一个业务分成多个工作流,不方便统计,因为节点即业务对象的状态,而一个节点只能属于一个工作流。
阶段
一个工作流有多个阶段,一个阶段可以有一个或多个节点。
阶段的概念,只是方便用于显示给用户。因为实际节点有10多个的时候,页面显示会很拥挤,分成三到五个阶段会合适一点。
当节点比较少时,可以直接使用节点的数据来显示。
节点
一个节点对应一个业务对象的状态,而且是系统内部状态。
显示给用户的外部状态,可以使用阶段的概念,也可以使用配置数据,给不同角色显示不同的名称。例如给卖家显示“已发货”,给买家显示“待收货”,当买家“待评论”,卖家则显示“已收货”。当然,一般来讲,使用统一的状态名才会比较好管理。
动作
会有数据表记录着从一个节点执行了什么动作,会有什么结果,不同的结果会去到什么节点。(具体可参考状态机概念)
页面
某状态要执行某动作,会去到哪些页面,这个是可以配置的。例如先get去到user/edit,再post去到user/edit-post。或者直接get去到 article/audit-post
配置的好处是,当这些节点在工作流中调整位置时,我们可以不改页面系统就自动调整好流程了。
缺点就是,一般来讲url数据是跟controller层在一起,而工作流核心的应该是业务层的东西。在工作流节点动作中配置url,会太耦合。需要开发人员知道在哪里调流程(URL就是控制流程的技术基础)。而且,需要为项目多个应用配置URL。
返回的数据格式
在一个强耦合的工作流项目中,因为返回的东西要通知工作流框架下一步要怎样做,于是有三种情况:
返回json给ajax请求
redirect url
直接显示HTML给浏览器
* id (primate_key)
* name
* desc
* phases 阶段列表,如果工作流的节点不多可以忽略不用
workflow_node 工作流节点
* id (primate_key)
* name
* desc
* workflow_id
* phase 该节点属于哪个阶段。如果工作流的节点不多可以忽略不用
* cfg 节点配置信息,里面可以有role_names(在不同角色中显示的节点名)
workflow_node_action 工作流节点动作表
* node_id (primate_key)
* action (primate_key)
* cfg
workflow_node_action.cfg结构如下:
或者应用在系列产品中,只要做好了各个节点模块,要出成品时,只需要配置一个即可。
否则简单的系统,直接在controller中配置URL,在业务层中直接写状态转换,这样可能更灵活简洁。
如果流程再要灵活点,例如,用户是男的或女的走的流程不一样,你就需要在cfg里面做详尽的配置。
应用
工作流如果做得好,最强大的应该是提供界面让用户自己创建工作流和节点,配置跳转规则。然而这个应该要有专业培训才能做得好。否则就只需要在数据库配置好数据,提供给开发人员使用即可。
与工作流有关的几个关键概念
工作流一个项目可以有多个工作流,对应多个工作。例如下订单流程、申请审核转正流程。
一个业务应该对应一个流程,如果它有多种情况,应该多设置节点和路径即可。如果将同一个业务分成多个工作流,不方便统计,因为节点即业务对象的状态,而一个节点只能属于一个工作流。
阶段
一个工作流有多个阶段,一个阶段可以有一个或多个节点。
阶段的概念,只是方便用于显示给用户。因为实际节点有10多个的时候,页面显示会很拥挤,分成三到五个阶段会合适一点。
当节点比较少时,可以直接使用节点的数据来显示。
节点
一个节点对应一个业务对象的状态,而且是系统内部状态。
显示给用户的外部状态,可以使用阶段的概念,也可以使用配置数据,给不同角色显示不同的名称。例如给卖家显示“已发货”,给买家显示“待收货”,当买家“待评论”,卖家则显示“已收货”。当然,一般来讲,使用统一的状态名才会比较好管理。
动作
会有数据表记录着从一个节点执行了什么动作,会有什么结果,不同的结果会去到什么节点。(具体可参考状态机概念)
页面
某状态要执行某动作,会去到哪些页面,这个是可以配置的。例如先get去到user/edit,再post去到user/edit-post。或者直接get去到 article/audit-post
配置的好处是,当这些节点在工作流中调整位置时,我们可以不改页面系统就自动调整好流程了。
缺点就是,一般来讲url数据是跟controller层在一起,而工作流核心的应该是业务层的东西。在工作流节点动作中配置url,会太耦合。需要开发人员知道在哪里调流程(URL就是控制流程的技术基础)。而且,需要为项目多个应用配置URL。
返回的数据格式
在一个强耦合的工作流项目中,因为返回的东西要通知工作流框架下一步要怎样做,于是有三种情况:
返回json给ajax请求
redirect url
直接显示HTML给浏览器
数据表
workflow table 工作流* id (primate_key)
* name
* desc
* phases 阶段列表,如果工作流的节点不多可以忽略不用
workflow_node 工作流节点
* id (primate_key)
* name
* desc
* workflow_id
* phase 该节点属于哪个阶段。如果工作流的节点不多可以忽略不用
* cfg 节点配置信息,里面可以有role_names(在不同角色中显示的节点名)
workflow_node_action 工作流节点动作表
* node_id (primate_key)
* action (primate_key)
* cfg
workflow_node_action.cfg结构如下:
{ // action的多个结果分别会跳到哪个节点 results: { success: { node_id: 111, } pending: { node_id: 222, } failed: { node_id: 444, } } // 强耦合的工作流系统,需要配置多个应用/module有关的东西 modules: { main: { // 要执行这个actin要进入的url action_urls: [ "user/edit", "user/edit-post", ], // action的结果,这里的results只需要配置与module有关的东西,如url results: { success: { next_url: "abc/def", next_url_method: "redirect" } pending: {} failed: {} } }, other_modules: {} } }
调用示例:
Class OrderController(){ function selectWorker(){ return view('selectWorker'); } function selectWorkerPost(){ // 控制器层的验证规则 // 调用服务层 OrderService::selectWorkder($orderId, $workerId); // 返回数据结果,可根据Workflow的处理结果和配置,自动跳转,如: return OrderService::getWorkflow()->processResult(); } } Class OrderService{ function selectWorkder($orderId, $workerId){ $order = Order::find($orderId); $wf = self::getWorkFlow(); // 工作流检查节点能否执行该动作 $wf->check($order->status, 'selectWorkder'); // 其它页面规则的验证 // 处理数据 $result = 'success'; // 记录工作流的动作,方便控制器调整数据和配置进行下一步处理,并返回业务对象下一个状态 $nextStatus = $wf->procces($orderOldStatus, 'selectWorkder', $result); // 保存数据和最新的状态 // 后续处理 Event::on('after-select-worker'); // 组装并返回数据 } }
结论
工作流引擎只适用在流程可能会变化的业务中。或者应用在系列产品中,只要做好了各个节点模块,要出成品时,只需要配置一个即可。
否则简单的系统,直接在controller中配置URL,在业务层中直接写状态转换,这样可能更灵活简洁。
如果流程再要灵活点,例如,用户是男的或女的走的流程不一样,你就需要在cfg里面做详尽的配置。
应用
工作流如果做得好,最强大的应该是提供界面让用户自己创建工作流和节点,配置跳转规则。然而这个应该要有专业培训才能做得好。否则就只需要在数据库配置好数据,提供给开发人员使用即可。