4. 条件分支与路由:if-else逻辑在工作流中的应用、路由节点设计、动态路径选择
说实话,很多刚接触工作流设计的朋友,都会把流程想成一条直线——输入进来,处理一下,输出出去。但现实世界哪有这么简单?
你想想看,一个订单金额超过1000块要走审批,低于1000块直接发货。用户是VIP会员走专属通道,普通用户走标准流程。这些判断逻辑,就是工作流里的「岔路口」。
我个人习惯把条件分支比作铁路的「道岔」。没有道岔,火车只能沿着一条轨道跑。有了道岔,才能把不同的车厢送到不同的目的地。今天我们就来聊聊,怎么在工作流里搭好这些「道岔」。
4.1 if-else逻辑:最朴素的决策单元
if-else这东西,写代码的人再熟悉不过了。但在工作流里,它长什么样?
我见过不少团队,直接把代码里的if-else搬到了工作流里,结果画出来的流程图跟蜘蛛网似的。其实没必要那么复杂。
工作流里的if-else,核心就三个要素:
- 条件表达式:判断的依据是什么?比如「订单金额 > 1000」
- 真分支:条件成立时走哪条路
- 假分支:条件不成立时走哪条路
举个例子,一个简单的客服工单分流:
{
"nodeType": "condition",
"name": "判断工单类型",
"expression": "input.ticket_type == 'technical'",
"trueBranch": "转技术部门",
"falseBranch": "转客服部门"
}
嗯,这里要注意。条件表达式不要写得太复杂。我在项目中遇到过有人把五六个条件用and/or串在一起,结果调试的时候自己都看不懂。我的建议是:一个条件节点只做一个判断。复杂逻辑?拆成多个节点串联。
4.2 路由节点设计:不止是二选一
if-else只能处理二选一。但实际业务中,经常遇到多选一的情况。比如:
- 根据用户等级:普通、银卡、金卡、钻石,走四条不同的推荐策略
- 根据错误类型:网络错误、参数错误、权限错误、未知错误,走四种不同的处理流程
这时候就需要「路由节点」了。说白了,路由节点就是一个多路开关。
我设计路由节点时,一般会包含这几个字段:
| 字段 | 说明 | 示例 |
|---|---|---|
| 路由字段 | 根据哪个字段做判断 | user.level |
| 路由表 | 字段值到分支的映射 | { "gold": "分支A", "silver": "分支B" } |
| 默认分支 | 没有匹配时的兜底 | 走标准流程 |
你看,这个结构其实很像switch-case。但比switch-case更灵活的是,路由表可以动态配置,甚至可以在运行时从数据库加载。
{
"nodeType": "router",
"name": "用户等级路由",
"routeField": "user.level",
"routeTable": {
"diamond": "diamond_pipeline",
"gold": "gold_pipeline",
"silver": "silver_pipeline",
"bronze": "bronze_pipeline"
},
"defaultBranch": "standard_pipeline"
}
4.3 动态路径选择:让流程自己「思考」
静态路由虽然好用,但不够聪明。什么叫动态路径选择?就是流程走到某个节点时,根据当前上下文、历史数据、甚至外部系统的反馈,实时决定下一步去哪。
举个例子。一个智能客服流程:
- 用户提问
- 调用NLP模型判断意图
- 根据意图路由到不同处理节点
- 处理完成后,根据用户满意度评分,决定是否转人工
你看,第三步和第四步的决策,都不是写死的。它们依赖于前一步的输出结果。这就是动态路径选择的核心——决策依赖运行时数据。
我个人习惯把动态路径选择分为两种模式:
- 数据驱动:根据输入数据的某个字段值做路由。比如根据用户所在地区路由到不同的数据中心。
- 策略驱动:调用一个策略服务,由策略服务返回下一步该去哪。比如A/B测试场景,由策略服务决定用户走实验组还是对照组。
策略驱动的实现方式,我一般会设计一个「策略节点」:
{
"nodeType": "policy",
"name": "A/B测试分流",
"policyService": "http://policy-center/api/decide",
"params": {
"user_id": "{{context.user_id}}",
"experiment_id": "exp_2024_001"
},
"outputField": "next_node"
}
这个节点调用外部策略服务,拿到结果后,把结果写入上下文的 next_node 字段。然后下一个路由节点根据这个字段做跳转。
4.4 实战中的坑与解法
讲了这么多理论,来点实际的。我在项目中踩过的几个坑,分享给你:
坑一:条件判断的「隐式转换」
有一次,我用 input.age > 18 做判断,结果 input.age 是个字符串 "18",而 18 是数字。在JavaScript里 "18" > 18 是 false。嗯,排查了半天。后来我强制要求所有条件表达式里,参与比较的字段必须先做类型转换。
坑二:路由表的「热更新」
路由表如果写死在配置文件里,每次修改都要重启服务。对于需要频繁调整路由的场景,我建议把路由表存在Redis或数据库里,流程引擎每次执行时实时拉取。这样改路由不用重启,秒级生效。
坑三:循环路由
动态路由最怕出现循环。A路由到B,B路由到C,C又路由回A。一旦出现这种循环,流程就会死循环,直到资源耗尽。我的解法是:每个节点设置一个「最大访问次数」,比如3次。超过次数就强制走默认分支,并触发告警。
4.5 小结
条件分支和路由,是工作流从「线性」走向「非线性」的关键。记住几个要点:
- 简单二选一用if-else,多选一用路由节点
- 路由表要支持动态配置,别写死
- 动态路径选择的核心是「决策与流程分离」
- 别忘了兜底策略和循环检测
下一章,我们会聊聊循环与迭代——当流程需要重复执行某个步骤时,该怎么设计。到时候见。