状态定义陷阱:状态爆炸、粒度、命名与合并
状态定义,说白了就是给系统画格子。格子画得太粗,业务逻辑糊成一团;格子画得太细,状态图能绕地球三圈。我见过太多项目在状态定义阶段就埋下了大坑,后面改起来简直是噩梦。
这一章咱们就聊聊状态定义里最常见的四个陷阱。嗯,每一个我都踩过。
状态爆炸问题
什么是状态爆炸?就是你的状态数量像癌细胞一样疯长。本来十几个状态能搞定的事,最后搞出上百个。
为什么会这样?我总结下来,最常见的原因有两个:
- 把组合当成状态:比如订单有“待支付”、“已支付”、“已发货”,有人非要拆出“待支付-未通知”、“待支付-已通知”、“已支付-未发货”……你想想看,这其实是两个维度的组合,不是独立状态。
- 把临时标记当成状态:比如“正在加载中”、“正在重试第3次”。这些是瞬态,不是业务状态。
怎么判断是不是状态爆炸?一个简单的标准:如果两个状态之间没有本质的业务行为差异,它们就不该是两个独立状态。比如“待支付-未通知”和“待支付-已通知”,系统对它们的处理逻辑完全一样,只是通知标记不同。那就用属性,别用状态。
状态粒度控制
粒度问题,说白了就是状态该粗还是该细。太粗了,状态机像个黑箱;太细了,状态图像张蜘蛛网。
我个人习惯用“行为一致性”来判断粒度。什么意思?就是看这个状态下的所有操作是否一致。
| 粒度 | 表现 | 后果 |
|---|---|---|
| 过粗 | 一个状态包含多种行为模式 | 条件判断满天飞,状态机形同虚设 |
| 过细 | 每个微小变化都成一个状态 | 状态数量失控,维护成本飙升 |
| 适中 | 同一状态下行为一致,变化由属性表达 | 状态清晰,扩展灵活 |
举个例子。一个工单系统,有人把“待审核-初审”、“待审核-复审”、“待审核-终审”拆成三个状态。但仔细想想,这三个状态下的操作都是“审核”,只是审核层级不同。更好的做法是:一个“待审核”状态,加一个“审核层级”属性。
状态命名规范
命名这事,看着小,坑起来要命。我见过一个项目,状态名叫“处理中”、“处理中2”、“处理中_新”。你猜哪个是哪个?没人说得清。
我建议遵循几个简单的规则:
- 动词 + 名词:比如“待支付”、“已发货”、“已完成”。一眼就能看出这个状态在干什么。
- 避免数字后缀:什么“状态1”、“状态2”,那是给自己挖坑。
- 统一时态:要么都用“待XX”,要么都用“已XX”,别混着来。
- 长度适中:中文 2-6 个字最佳,太长不好读,太短容易歧义。
命名对照表:
| ❌ 糟糕命名 | ✅ 好命名 | 说明 |
|---|---|---|
| 状态A | 待审核 | 明确表达了业务含义 |
| 处理中2 | 二次处理中 | 数字后缀改为语义化描述 |
| 已完成_旧 | 已归档 | 用业务术语代替模糊标记 |
| doing | 执行中 | 统一使用中文 |
命名规范还有个好处:代码可读性。你想想看,新同事看到“待支付”和“状态3”,哪个更容易理解?
状态冗余与合并
冗余状态,就是那些看起来不同、实际上行为一致的状态。我遇到过最夸张的一个案例:一个电商系统里,“已取消”和“已关闭”两个状态,代码里处理逻辑一模一样。问产品经理,他也说不清区别。最后合并成一个“已取消”。
怎么发现冗余状态?几个信号:
- 相同的行为映射:两个状态对同一事件的响应完全一样。
- 相同的后续状态:两个状态能到达的下一个状态集合完全一致。
- 业务上无法区分:问业务方,他们也说不出这两个状态到底有什么不同。
合并状态的时候,要注意一点:不要丢失信息。如果两个状态虽然行为相同,但业务上确实需要区分(比如统计报表要用),那就用属性来区分,而不是用状态。
下面这张图,是我总结的状态定义核心逻辑,帮你快速判断一个状态该不该存在:
最后说一句:状态定义没有银弹。每个系统都有自己的业务特点,但核心原则是一样的——状态服务于业务,别让状态定义绑架了业务。我见过太多人为了追求“完美的状态机”,把简单问题复杂化了。记住,状态机是工具,不是目的。