Appearance
业务流程与状态机设计(V10)
上位机里的按钮不等于设备动作,设备报警也不等于软件一定停机。真正需要设计的是:什么事件在什么条件下发生,系统采取什么后果,状态如何变化,什么时候复位,以及留下什么证据。
V10 不要求每次改一个状态条件都重新画完整状态机。
1. 先分任务
| 当前任务 | 推荐路径 |
|---|---|
| “现在这个按钮什么时候可用?” | Read-Only Trace |
| “连续 5 次才报警,但流程继续” | Execution / BehaviorPatch |
| “以前停止后能回 Ready,最近回不去了” | RegressionFix |
| “新增一个测试阶段/恢复流程” | Discovery / State Design |
| 状态分散、同类 Bug 长期反复 | 显式 Architecture Hotspot Review |
现有系统只改一条明确 transition 时,优先最小 BehaviorPatch;新主流程才需要完整状态表和状态图。
2. Behavior Contract 是最小状态修改单元
涉及运行规则时先写:
text
Trigger:
Condition:
Action:
Reset:
Record:
NonGoals:例如:
text
Trigger: 停机窗口残余电流检测
Condition: 连续 5 个有效样本达到阈值
Action: AlarmOnly,当前测试继续
Reset: 任意正常样本清零;下一停机窗口重新计数
Record: 保存 5 个 Raw/工程值、阈值、时间戳
NonGoals: 不修改下一测试窗口启动条件,不改高压控制这六行比“增加一个报警状态”更不容易被误实现。
3. 事件后果先分类,再谈状态
| 类型 | 是否改变主流程 | 典型表现 |
|---|---|---|
Information | 通常不改变 | 状态展示/记录 |
Advisory | 不应硬阻断 | 提示,必要时用户确认 |
AlarmOnly | 流程继续 | 报警 + 记录 |
InterlockFault | 阻断/停止 | 故障状态 + 明确恢复 |
重要:通信超时没有固定后果
旧式设计常写:
text
通信超时 → FaultStop这是不安全的默认假设。
同一个“通信超时”在不同设备/阶段可能是:
text
Information → 一次后台轮询失败,下一周期再试
AlarmOnly → 辅助设备离线,但当前测试继续
Advisory → 用户确认是否继续
InterlockFault→ 关键安全设备失联,必须停止后果必须来自业务规则,而不是由异常类型自动决定。
4. 软件状态、设备状态、事件后果不要混成一个枚举
建议至少区分概念:
text
WorkflowState
DeviceState
EventConsequence例如:
text
WorkflowState = Running
ScopeState = Disconnected
EventConsequence = AlarmOnly这在某些项目完全可能成立:示波器掉线被记录报警,但其它本地流程继续。
如果把所有东西都塞进 FaultStop,后续会出现状态组合爆炸。
5. 新流程的状态列表
只有新流程/大改版时才建议建立完整表。
| 状态 | 业务含义 | 允许操作 | 禁止操作 | 进入条件 | 退出条件 |
|---|---|---|---|---|---|
| Idle | 无活动测试 | 连接、配置 | 危险运行命令 | 初始化完成 | 准备任务 |
| Ready | 设备/参数满足启动条件 | 启动、允许参数修改 | 未授权危险动作 | 前置检查通过 | Start/Fault |
| Running | 正在执行核心流程 | 停止、查看状态 | 修改关键参数 | Start 成功 | Complete/Stop/Fault |
| Stopping | 正在有序停止 | 只允许必要查看 | 再次启动 | Stop 请求 | Stopped/Fault |
| Completed | 本轮完成 | 保存、复盘、新任务 | 改写已冻结结果 | 正常完成 | 新任务 |
| Faulted | 已被 InterlockFault 阻断 | 查看原因、恢复 | 自动继续危险动作 | 联锁故障 | Reset/Recovery |
状态名可按项目调整。关键不是名字统一,而是含义和后果一致。
6. Transition 表要显式写后果和证据
| Current | Trigger | Condition | Action | Consequence | Next | Reset/Record |
|---|---|---|---|---|---|---|
| Ready | 用户 Start | 参数合法且关键设备 Ready | 开始流程 | Information | Running | 记录参数版本 |
| Running | 用户 Stop | 任意运行阶段 | 发起有序停止 | Information | Stopping | 记录停止来源 |
| Running | 辅助设备超时 | 本项目定义可继续 | 提示+记录 | AlarmOnly | Running | 记录原始错误 |
| Running | 安全联锁断开 | 联锁条件成立 | 停危险动作 | InterlockFault | Faulted | 保存联锁证据 |
| Faulted | Reset | 原因已解除且满足恢复条件 | 清故障 | Information | Ready | 记录人工确认 |
不要只写 Running → Faulted,否则很难 Review “为什么会去 Faulted”。
7. 按钮使能是状态机的投影,不是第二套业务规则
例如启动按钮:
text
CanStart
= WorkflowState == Ready
&& RequiredDevicesReady
&& ParametersValid
&& NoBlockingInterlockUI 可以基于这个结果禁用按钮,但后端真实 Start 入口仍应保护关键业务条件。
反模式:
text
UI 禁用了按钮
→ 认为系统安全
→ 其它调用入口仍能直接执行 Start危险动作不能只靠 UI 控制。
8. 连续 N 次、窗口和 Reset 是状态,不是普通 if
例如“连续 5 次超阈值”至少要明确:
text
ResetOnGood?
InvalidSamplePolicy?
ReportOnce?
ResetBoundary?可能需要状态:
text
ConsecutiveCount
ReportedThisWindow
WindowId但不要为了这三个状态就创建一个全新状态机框架;如果现有逻辑有稳定 owner,局部实现即可。
9. 运行窗口/阶段切换要定义边界
工业测试常见:
text
Prepare
→ TestWindow
→ StopWindow
→ TestWindow
→ ...
→ Complete跨窗口状态必须明确:
- 哪些计数清零;
- 哪些缓存保留;
- 哪些健康查询暂停;
- 哪些设备状态只读缓存;
- 哪些告警每窗口只报一次;
- 下一窗口由什么条件启动。
否则“上一窗口留下的状态”会成为非常隐蔽的回归源。
10. Stop / Fault / EmergencyStop 不要混用
Normal Stop
用户主动停止,通常要求:
- 有序停止任务;
- 保存必要数据;
- 资源回到可再次运行状态。
Interlock Fault
业务/安全条件触发,需要:
- 立即或受控终止特定动作;
- 明确故障原因;
- 明确 Reset 条件。
Emergency Stop
如果项目存在真正急停,需要单独按设备安全规范设计;不要简单等同于普通 StopAsync()。
软件文档必须写清它能做什么、不能替代什么硬件安全措施。
11. Recovery 是一等流程
需要回答:
text
故障原因解除后自动恢复还是人工确认?
恢复到 Ready、Idle 还是回到原阶段?
未完成的数据如何处理?
设备是否需要重新同步参数?
旧 session/task 是否已结束?“清掉红色提示”不是恢复完成。
恢复后的软件状态、设备状态和业务数据必须重新一致。
12. RegressionFix:状态行为以前正常时先比较 transition delta
用户说:
text
以前点停止后可以再次启动,现在不行先比较:
Stop后 NextState 是否变化;- 新增了哪个 guard;
- Reset 是否少清一个 flag;
- 设备状态是否新增缓存;
- 最近是否引入新的 Fault 后果;
- Timer/session 是否仍然占用资源。
建立:
text
KnownGood transition
vs
Current transition不要先把所有状态机代码重构一遍。
13. 操作员状态与维护状态分层
主界面通常展示:
text
待机 / 自检中 / 就绪 / 测试中 / 停止中 / 已完成 / 故障维护诊断可以有更细:
text
ScopeDisconnected
RawRecoveryPending
MESRetrying
StopAwaitingDeviceAck不要让实验人员面对几十个内部枚举值;也不要为了界面简洁把底层诊断证据丢掉。
详见 操作员界面与维护诊断分层。
14. 验证按状态风险选
BehaviorPatch
如果只改连续次数/提示后果:
text
边界前不触发
达到条件触发
Reset 正确
NonGoals 未改变V3 状态机/联锁
至少关注:
text
Normal Start
Normal Stop
Fault Enter
Fault Reset
Stop during running
Repeated Start blocked
Window/Stage transition
Recovery
WorkflowSmoke危险真实设备动作仍需人工授权。
15. 两个可复制 Prompt
查当前状态行为
text
$host-computer-dev
只做 Read-Only Trace。
我想确认:
【例如:示波器通信超时后当前测试到底会不会停止】
请追踪最短链并输出:
Trigger / Condition / Action / NextState / Reset / Record。
如果 UI 状态和后端真实后果不同,请明确指出。
不要修改代码或重画整个状态机。明确状态规则修改
text
$host-computer-dev
这是一个已确认的 BehaviorPatch,不需要重新做完整需求分析。
Trigger:
Condition:
Action:
Reset:
Record:
NonGoals:
请定位当前 transition owner,做最小修改。
如果 Action 会改变 AlarmOnly / InterlockFault 或 Stop/Continue 后果,按 V3 做 focused workflow 验证。
不要顺手重构整个状态机。16. 常见反模式
| 反模式 | 后果 |
|---|---|
所有异常都 FaultStop | 非关键故障意外阻断流程 |
| “报警”没有 Action | 实现只能猜后果 |
| UI 按钮禁用就是唯一联锁 | 其它入口可绕过 |
| 连续 N 次不定义 Reset | 状态跨窗口残留 |
| Stop/Fault/EStop 共用一个语义 | 恢复和安全边界混乱 |
| 只清 UI 红色,不恢复真实状态 | 看起来恢复、实际不能运行 |
| 改一条 transition 重画全状态机 | 小改成本失控 |
下一步
一句话原则
状态机先定义业务后果,再定义新状态;明确的一条规则只改一条规则,新主流程才做完整状态设计。