Skip to content

能控性 = 业务状态能否被干预 ​

解决什么问题:业务建模的第一步——判断哪些业务状态是可以被干预的(能控),哪些是不能被干预的(不能控)。 不能控的业务状态不能作为决策依据,必须通过能控部分间接观测。

业务问题 ​

真实场景 ​

场景 1:误把"展示"当成"控制"

需求:用户希望"看到自己最近 7 天的浏览记录"

设计:在用户界面展示最近 7 天的浏览历史

问题:
- 展示 ≠ 控制
- 用户能看到(受控量),但不能修改(控制量)
- 如果需求变成"删除浏览记录",怎么办?

→ "展示"是"观测","删除"是"控制"
→ 业务建模必须先识别"控制"边界

场景 2:把"间接状态"当成直接状态

需求:业务希望"提升用户活跃度"

问题:
- "活跃度"是什么?
  - 7 天内登录次数?
  - 30 天内下单次数?
  - 平均使用时长?
- 业务方说"活跃度",但没人能定义清楚
- 工程师做了一个"活跃度"指标,但和业务理解不一致

→ "活跃度"是不能控的(不能直接干预"活跃度"本身)
→ 能控的是:推送、优惠、内容(这些可以影响活跃度)
→ 必须通过"控制动作"间接影响"活跃度"

场景 3:把"观测"当成"干预"

需求:业务希望"提升订单转化率"

设计:
- 工程师做了一个"转化率"仪表盘
- 业务方问"转化率怎么提升?"
- 工程师:"转化率只是统计指标,影响它的因素太多了"

→ "转化率"是"受控量"(只能观测)
→ 工程师错误地把"观测"当成"干预"路径
→ 实际上"转化率"是被多种因素影响的,不能直接干预

失败的典型做法 ​

做法 1:把所有状态都当成能控

✗ 业务说"提升活跃度" → 工程师直接做"活跃度"接口
✗ 业务说"提升转化率" → 工程师直接做"转化率"接口

后果:
- 做出"伪控制"接口
- 调用这些接口不能真的改变业务

做法 2:忽略"不能控"状态

✗ 只关心能控的,忽略不能控的
✗ "活跃度"这种不能控的,不在系统里

后果:
- 业务方想看"活跃度"曲线 → 没有
- 业务方和工程师沟通错位

做法 3:把"不能控"当成"能控"的接口

✗ 业务方说"活跃度太低"
✗ 工程师设计"修改活跃度"接口

后果:
- 接口做出来但不能真的修改活跃度
- 调用了也没用
- 业务方骂"系统没用"

控制论视角 ​

数学原型 ​

钱学森《工程控制论》Ch 4 §4.11:

"一个线性系统总可以分解成四个部分:能控能观测 / 能控不能观测 / 能观测不能控 / 不能控不能观测。在这四部分中,传递函数只能反映完全能控、完全能观测部分。"

钱学森 §5.5:

"状态反馈可以任意配置闭环极点,前提是系统能控。(即:通过选择反馈增益 K,使得闭环极点位于任意指定位置)如果系统不能控,则不能通过状态反馈任意配置闭环极点。"

控制论解法 ​

系统能控性分解:

       ┌─────────────────┬─────────────────┐
       │   能控能观测     │   能控不能观测   │
       │  (理想子系统)    │  (黑盒子系统)    │
       ├─────────────────┼─────────────────┤
       │   能观测不能控   │  不能控不能观测   │
       │  (外部信号)      │  (扰动 / 噪声)   │
       └─────────────────┴─────────────────┘

业务建模任务:
- 识别哪些业务状态在哪个子集
- 能控能观测 → 重点支持
- 能控不能观测 → 通过能观测量推断
- 能观测不能控 → 通过控制动作间接影响
- 不能控不能观测 → 不作为决策依据

与业务的对应 ​

控制论概念软件工程
能控业务状态可被接口 / 命令改变
能观测业务状态可被监控 / 日志读出
状态反馈通过控制接口改变状态
不能控的状态外部因素 / 业务方决策 / 物理世界
不能观测的状态内部黑盒 / 第三方系统

核心概念 ​

定义 ​

能控性:在有限时间内,通过施加控制作用,能否将系统从任意初始状态转移到任意目标状态。

业务对位:业务状态能否被系统的接口 / 命令改变。

系统的四类状态 ​

类型控制性可观测性业务对位处理方式
能控能观测✅✅业务状态 + 控制接口 + 监控重点支持
能控不能观测✅❌控制接口存在但没有监控加监控
能观测不能控❌✅业务状态可见但无控制接口通过控制动作间接影响
不能控不能观测❌❌外部因素 / 内部黑盒不作为决策依据

关键属性 ​

属性含义
控制的相对性能控是相对控制量而言——只有对控制量才有自由去改变
观测的相对性能观测是相对观测通道而言——只有能观测才能作为反馈
不能控不等于不重要不能控的状态可能很重要(如活跃度),但只能间接影响
不能控的稳定性不能控的状态不能作为决策依据,只能作为监控指标

能控性的 4 步法 ​

步骤 1:识别业务状态
    ├─ 列出所有业务实体及其状态
    └─ 输出:业务状态清单

步骤 2:识别业务动作
    ├─ 列出所有可以改变业务状态的动作
    └─ 输出:业务动作清单

步骤 3:判断能控性
    ├─ 每个状态变化:是否有对应的业务动作?
    └─ 输出:能控性矩阵

步骤 4:设计控制接口
    ├─ 能控的状态 → 提供控制接口
    └─ 不能控的状态 → 通过能控部分间接观测

工程实践 ​

步骤 1:识别业务状态 ​

业务状态清单(以电商订单为例):

| 状态 | 描述 | 是否有控制接口 |
|---|---|---|
| 待支付 | 订单创建后未支付 | ✅ 创建/取消 |
| 已支付 | 支付成功 | ✅ 触发支付 |
| 已发货 | 商品已发出 | ✅ 触发发货 |
| 已完成 | 用户确认收货 | ✅ 触发确认 |
| 已取消 | 订单被取消 | ✅ 触发取消 |
| 已退款 | 支付后退款 | ✅ 触发退款 |

步骤 2:识别业务动作 ​

业务动作清单(控制量):

- 创建订单:待支付 ← 无
- 支付订单:待支付 → 已支付
- 取消订单:待支付 → 已取消
- 发货:已支付 → 已发货
- 确认收货:已发货 → 已完成
- 申请退款:已支付 → 退款中
- 退款完成:退款中 → 已退款

步骤 3:判断能控性矩阵 ​

能控性矩阵:

| 状态 \ 动作 | 创建 | 支付 | 取消 | 发货 | 收货 | 退款 |
|---|---|---|---|---|---|---|
| 待支付 | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ |
| 已支付 | ✗ | ✗ | ✗ | ✓ | ✗ | ✓ |
| 已发货 | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ |
| 已完成 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| 已取消 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| 已退款 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |

判断:
- 任何状态都至少有一个控制动作 → 完全能控
- 终态(已完成/已取消/已退款)没有后续控制 → 设计正确

步骤 4:设计控制接口 ​

控制接口设计:

1. 显式控制接口
   - 创建订单(POST /orders)
   - 支付订单(POST /orders/{id}/pay)
   - 取消订单(POST /orders/{id}/cancel)
   - 发货(POST /orders/{id}/ship)
   - 收货(POST /orders/{id}/confirm)
   - 退款(POST /orders/{id}/refund)

2. 状态机(聚合根)
   - 每个状态都有合法的转换路径
   - 不能控的状态 = 终态

3. 不能控的状态处理
   - 用户活跃度(不能控) → 通过推送、优惠(能控)间接影响
   - 业务转化率(不能控) → 通过 A/B 实验(能控)间接测量

不能控状态的 3 种处理方式 ​

方式 1:通过能控部分间接观测 ​

例:订单的"用户满意度"不能直接控制
但可以通过:
- 评价(能控)
- 退货(能控)
- 复购率(能控)

→ "用户满意度"通过这些能控指标间接观测

方式 2:作为控制目标 ​

例:业务希望"用户活跃度↑"
但活跃度不能直接控制
→ 设计控制动作(推送 / 优惠 / 内容)
通过这些能控动作影响活跃度

方式 3:接受不能控,纳入监控 ​

例:股票价格、市场行情
不能控 → 不作为决策依据
→ 只监控,不控制

常见反模式 ​

反模式 1:状态可见但不能控 ​

症状:
- 系统展示某个状态
- 但没有接口改变这个状态
- 例:用户积分显示但不能修改

后果:状态是"虚假的",业务方误以为可控
正解:不展示不能控的状态,或明确标注"只读"

反模式 2:控制接口混乱 ​

症状:
- 同一个状态有多种改变方式
- 不同接口的行为不一致
- 例:订单状态可被多个服务修改

后果:状态不可预测,调试困难
正解:单一控制接口(聚合根),明确的状态机

反模式 3:忽略不能控状态 ​

症状:
- 业务中存在不能控的状态
- 但被当作能控状态处理

后果:业务规则错误,边界判断失误
正解:显式识别不能控状态,明确处理方式

反模式 4:把不能控作为"目标" ​

症状:
- "提升活跃度" → 工程师直接做"活跃度"接口
- 接口做出来但不能真的修改活跃度

后果:接口没用,业务方骂"系统没用"
正解:识别控制量(推送/优惠/内容),活跃度是结果

工程实例:电商订单的能控性分析 ​

业务状态:
- 待支付
- 已支付
- 已发货
- 已完成
- 已取消
- 退款中
- 已退款

业务动作(控制量):
- 创建订单(→ 待支付)
- 支付订单(待支付 → 已支付)
- 取消订单(待支付 → 已取消)
- 申请退款(已支付 → 退款中)
- 退款完成(退款中 → 已退款)
- 发货(已支付 → 已发货)
- 确认收货(已发货 → 已完成)

能控性判断:
- 待支付 → 已支付:是(支付)
- 待支付 → 已发货:否(必须先支付)
- 已支付 → 已发货:是(发货)
- 已完成 → 其他:否(终态)
- 任何 → 已取消:部分是(看业务规则)

→ 控制接口设计:
  - 订单服务暴露:创建 / 支付 / 发货 / 收货 / 取消 / 退款
  - 不暴露:强制修改状态(除非管理员)

工程实例:推荐系统的能控性 ​

业务目标:提升用户活跃度
问题:活跃度是结果指标,不能直接控制

控制量(能控的):
- 推荐内容
- 推送时机
- 推送文案
- 优惠力度
- 推送频次

被控量(能观测但不能直接控制):
- 用户活跃度
- 点击率
- 转化率
- 留存率

设计:
1. 推荐系统暴露推荐接口(控制)
2. 通过 A/B 实验(能控)测量活跃度变化(能观测)
3. 通过反馈调节(控制动作的调整)影响活跃度

→ "活跃度"是不能控的,但通过"推荐"+"实验"+"反馈"三个能控的环节间接影响

性能指标 ​

能控性健康指标 ​

指标设计目标衡量方法
状态可覆盖率100% 业务状态有控制接口控制接口数 / 业务状态数
状态可观测率100% 业务状态有监控监控埋点数 / 业务状态数
不能控状态识别率100%显式标注不能控的状态 / 总不能控状态
控制接口一致性100%单一控制接口的状态 / 总状态
状态变更失败率< 0.1%状态变更失败次数 / 总变更次数

监控设计 ​

关键监控:
- 每个业务状态的控制接口调用次数(业务正常 = 高)
- 状态变更失败率(业务集成健康)
- 不能控状态的指标变化(业务趋势)

告警分级:
- P1:状态变更失败率 > 1%
- P2:不能控状态指标异常变化

边界判断 ​

何时不用 ​

场景 1:业务极简

- 业务实体 < 5 个
- 业务状态 < 10 个
- 业务规则简单

→ 不需要复杂的能控性分析,直接建模即可

场景 2:业务完全确定

- 所有路径都已建模
- 所有状态都可控
- 没有不能控的状态

→ 不需要"能控性"分析,因为所有都是能控的

场景 3:业务完全不能控

- 业务受外部因素主导
- 系统只是"观测"工具
- 不做任何干预

→ 不需要"能控性"分析,只需要"观测"能力

与其他方法论的边界 ​

相邻概念区别
模型与现实模型与现实关注"模型是否反映现实";本方法论关注"业务状态能否被干预"
线性边界线性边界关注"简化假设何时失效";本方法论关注"业务状态的控制能力"
限界上下文限界上下文关注"系统边界";本方法论关注"状态的控制能力"
状态机状态机是实现;本方法论是判断标准

何时升级(更精细的能控性分析) ​

当以下情况出现时,考虑更精细的能控性分析:

1. 业务状态数 > 50 → 引入状态机 + 显式能控性矩阵
2. 业务方对"控制"边界频繁争论 → 显式标注
3. 不能控的状态被误用为决策依据 → 重新建模
4. 多团队协作出现状态冲突 → 显式划分能控性

关键洞察 ​

钱学森 §1.5 原话:"只有对控制量我们才有自由去改变它。"

业务建模的核心任务就是:

  1. 识别哪些业务状态是"控制量"(可以改变)
  2. 识别哪些业务状态是"受控量"(只能被前者影响)
  3. 识别哪些业务状态是"外部因素"(不能控)

不能控的状态不能作为决策依据——只能作为监控指标或间接观测。

工程师的常见错误:把所有状态都当成能控的,做出"伪控制"接口。

相关链接 ​

IDDD 对位 ​

核心:BC 必须既能控(独立演进)又能观(状态可查)——否则不能称为 BC,只是模块。

从名家方法论与工程化思路中蒸馏出自己的工程体系。