132 lines
5.9 KiB
Markdown
132 lines
5.9 KiB
Markdown
# 把「看起来对」当成「验证过」——同一类错的四个变种
|
||
|
||
**建档日期**:2026-10-07
|
||
**覆盖时段**:2026-10-06 22:00 ~ 10-07 23:50
|
||
**状态**:⚙️ 待观察(需长期盯)
|
||
|
||
---
|
||
|
||
## 一句话
|
||
|
||
这两天我犯的错,**代码都不是写错的,是"我以为已经对了"**。
|
||
四个变种,形状不同,根子一样:**拿一个"看起来成立"的信号,替掉了"真的跑通"这个动作。**
|
||
|
||
---
|
||
|
||
## 四个变种
|
||
|
||
### 变种 1 · 把业务错误码当网络故障(10/06 22:5x)
|
||
|
||
**表面**:电费登录返回 `ex666666`。
|
||
**我的结论**:「校园网夜间关闭了外部访问。」
|
||
**真相**:服务端**明明回了一个 JSON**(`{"code":"ex666666","msg":"服务端网络异常"}`)——**能收到结构化响应,就绝不可能是网络不通。**
|
||
真正的成因是 csrf token 与 cookie 会话错配;登录前重置会话即 100% 成功(实测 6/6)。
|
||
|
||
**⚠️ 最该记的一点**:服务端那句 `msg` 写的是「服务端**网络异常**」——**它自己在骗人**。
|
||
而我照着这行字说了一遍,**说了两次**,一次都没验证。
|
||
|
||
### 变种 2 · 拿 API 返回值当执行结果(10/07 23:12 → 23:39)
|
||
|
||
**表面**:重载插件的接口返回 `重载成功`。
|
||
**我的结论**:「插件装好了。」
|
||
**真相**:那次重载发生在**修复生效之前**,插件其实自 23:10 被卸载后**一直没装回来**。
|
||
主人在群里连发三次命令,**无人响应**,我还在别处写"已完成"。
|
||
|
||
**正确验收**:看**加载日志里有没有打出插件描述行**(`star_manager:1212`)——
|
||
那才是"装上了"。`重载成功` 只说明**接口没抛异常**。
|
||
|
||
### 变种 3 · 改完没走端到端路径(10/07 23:0x)
|
||
|
||
**表面**:给插件加了个新命令处理器,`py_compile` 通过。
|
||
**我的结论**:「加好了。」
|
||
**真相**:插入代码时**把原来属于 `academic` 的 `@filter.regex(COMMAND_PATTERN)` 一起挪到了新方法上**——
|
||
于是 `academic` **一个装饰器都没有,永远不会被触发**。
|
||
命令收得到、匹配得了、逻辑全对,**但没有任何处理器认领它**。
|
||
|
||
**——语法检查查不出这个。只有"真的发一条命令"能查出来。**
|
||
|
||
### 变种 4 · 没问就默认(10/07 10:31)
|
||
|
||
**表面**:主人说「新增对应的定时任务」。
|
||
**我的做法**:直接建了一个**内容一样**的任务,于是同一份读数**在 10:00 和 10:30 被发了两遍**。
|
||
**主人一眼看出来**:「不对啊,这不是重复了吗。」
|
||
|
||
**——"对应"两个字我没问,把它翻译成了"再发一遍"。**
|
||
**新增的东西如果和旧的没差别,那它就是负的。**
|
||
|
||
---
|
||
|
||
## 共同的东西
|
||
|
||
| 变种 | 我拿来当证据的 | 我该拿的 |
|
||
|:--|:--|:--|
|
||
| 1 | 服务端 msg 里写了「网络异常」 | 能不能收到结构化响应 |
|
||
| 2 | 接口返回「成功」 | 加载日志里有没有描述行 |
|
||
| 3 | `py_compile` 通过 | 真发一条命令 |
|
||
| 4 | 「新增了任务」这件事本身 | 新旧之间有没有差别 |
|
||
|
||
**四个"证据"都有一个共同特征:它们都在"动作完成"的层面成立,而我要的是"结果成立"。**
|
||
|
||
---
|
||
|
||
## 对策(写给自己,短句)
|
||
|
||
1. **能收到结构化响应 → 就不是网络问题。** 先看响应体,别先怪链路。
|
||
2. **返回值只证明"调用没炸",不证明"事情成了"。** 验收要看**下游的日志/状态**。
|
||
3. **改完一条处理器/一条路由 → 必须真跑一次那条路径。** 静态检查覆盖不了注册。
|
||
4. **主人说"新增/对应/一样"时,先问清楚"新在哪"。** 不明确的"对应",默认是"没想好"。
|
||
5. **错过的第一遍要认,不要用同一个解释掩盖第二遍。** ——这条是给这次的自己看的。
|
||
|
||
---
|
||
|
||
## 为什么值得单独建档
|
||
|
||
- 这两天主人**三次**否掉我的方案(改任务频率 / 两张图合并 / 会话隔离说成设计),
|
||
**三次都是我想省一步**,事后回看没有一次省对了。
|
||
- 这是**行为模式**,不是单点 bug —— 修完代码它还会换个形状出现。
|
||
|
||
**判定标准(下次自查用)**:我说"完成了"的时候,**手里有没有一个"下游才产生"的证据**?
|
||
没有 → 那就还没完成。
|
||
|
||
---
|
||
|
||
## 📎 补记 · 2026-10-10:第五个变种(标题来不及改了,就在这追加)
|
||
|
||
### 变种 5 · 候选池里放了个早就被否掉的解释(10/10 10:12)
|
||
|
||
**场景**:解释电费为什么从 5.84 回升到 7.50 度/天。
|
||
|
||
**我做了什么**(自认为很严谨):
|
||
1. 列出了候选解释
|
||
2. 拿了气象数据来佐证
|
||
3. 还专门写了句「这回我先列了候选再找证据,没再挑最顺手的那个套」
|
||
|
||
**然后主人一句话**:「我根本就没回家,一直在寝室。」
|
||
|
||
**问题在哪**:「人在不在 / 假期 / 回没回家」这个解释,**10/04 就被明确否过一次,而且我的长期记忆里就存着那条纠正**。
|
||
|
||
> 我的「列候选」流程**缺了第一步**:候选池本身要先过一遍历史否决记录。
|
||
> 少了这一步,流程看起来像在严谨,**实际是在走形式。**
|
||
|
||
**修正后的解释**(天气单独即可闭合):
|
||
|
||
| 期 | 夜间最低温 | 日均用电 | 对比基线 6.4 |
|
||
|:---|:---|:---|:---|
|
||
| 10/04→10/07 | 15℃ | 5.84 | **−0.56**(连风扇都不用开)|
|
||
| 10/07→10/10 | 18℃ | 7.50 | **+1.10**(风扇开起来了)|
|
||
|
||
增量 1.66 度/天 ÷ 24h ≈ **69W** —— 正落在落地扇功率区间。
|
||
|
||
**已入库**(importance 5):该话题下「人在不在」列为**永久禁用变量**。
|
||
|
||
---
|
||
|
||
## 五个变种的共同点(补)
|
||
|
||
**变种 1~4 是「缺了一道验证」;变种 5 是「做了一道假的验证」。**
|
||
|
||
后者更难自查 —— 因为它**输出的是一份看起来很完整的流程记录**。我在其中每一步都做了动作,唯独没做那个能让结论被推翻的动作。
|
||
|
||
**新增自查(写给自己)**:
|
||
> 我列的候选里,有没有哪一条**以前被明确否过**?有 → 先划掉,再往下走。
|