周一早上,我的 Bug 把辞职信拍在了键盘上。
"从今天起,别再叫我偶现了。我有名字,叫输入边界。"
一、Bug 说,它已经替我背了三年锅
我问它为什么离职。
它打开一张工单,指着备注:"你写了'用户操作有问题',但用户只是点了两次。"
我说:"那应该防抖。"
它又打开一张:"这次用户只点了一次,是网络重试。"
我说:"那再加个锁。"
Bug 把第三张工单推过来:"这次是空字符串。你连门都没装,先买了三把锁。"
我沉默了。它的离职理由比我的需求文档还完整。
二、它要求在离职证明上写明真实姓名
以前我的错误处理,主要靠一句非常有包容心的话:
js
try {
await saveOrder(input);
} catch (error) {
console.log('出错了');
}
"你看看,"Bug 说,"我把案发现场留给你,你把现场擦了,还挂了块'出错了'的牌子。"
它提出三个交接条件:
- 记录正在做什么,用不含个人信息的请求编号关联现场。
- 保留原始异常,让后续排查能找到原因。
- 不把密码、令牌和用户完整输入塞进日志。
于是我先把演示代码改成这样:
js
async function submitOrder(input, requestId) {
try {
return await saveOrder(input);
} catch (cause) {
throw new Error(`保存订单失败,requestId=${requestId}`, { cause });
}
}
这段代码只演示保留异常链。请求编号需要由可信入口生成;它不会自动解决重试、幂等或输入校验。错误还得在上层统一记录和处理,不能靠多抛一次就算修好了。
Bug 看完,第一次没有冷笑:"至少以后你能认出我了。"
三、它的继任者叫"应该没问题"
我按照交接单补了空值校验,为重复请求设计幂等标识,再把失败重试的场景加进测试。
我宣布:"这下应该没问题了。"
Bug 突然停下收拾行李的手。
"你刚才说的那位,是我的继任者。"
我赶紧把话改成:"目前验证了空输入、重复请求和一次模拟超时;并发和服务重启后的表现,还需要继续验证。"
它点点头,在离职申请上签了字。
原来让一个 Bug 退休,不是把它从列表里划掉,而是把它出现的条件、修复的范围和还没验证的地方写清楚。
四、离职后,它寄来一张明信片
一周后,我收到一张来自生产环境的明信片。
上面写着:
"新工作挺好,大家都叫我边界条件。不用背锅,有自己的测试用例。"
背面还有一行小字:
"你们那个
catch里,别再写'忽略'了。那是给我留的返聘通道。"
我关掉明信片,给工单补上了复现步骤。
这次,没有写"偶现"。
原创程序员寓言,人物与情节虚构,AI 辅助创作与配图。代码为说明错误处理思路的简化示例。