为什么你修了一个bug,系统反而多了三个新bug?
版权声明
我们非常重视原创文章,为尊重知识产权并避免潜在的版权问题,我们在此提供文章的摘要供您初步了解。如果您想要查阅更为详尽的内容,访问作者的公众号页面获取完整文章。
2017年,美国圣地亚哥的一所医院更新了电子病历系统。
新版系统上线后,ICU的病人死亡率在三个月内上升了14%。
医院紧急排查,追溯到新系统上线前后的唯一差异:护士的药品核查流程被改写了。新的流程要求护士在给药前必须在系统中勾选12项核查项目,老流程只需要5项。
护士们每天要勾选1000多次。在高压的ICU环境里,她们开始跳步——不是故意跳过,是根本没时间按流程走完。系统越完善,操作越复杂,人越容易绕过系统。而绕过系统的那一步,恰好是防止用药错误最关键的一步。
这不是一个关于医疗的故事。这是一个关于你每天都在犯的错误的隐喻。
一个你可能经历过无数次的工作日
某个深夜,你在做一个订单模块。发现一个bug:用户取消订单后,系统没有给用户退款。
你打开代码,找到问题所在:cancel_order() 函数里调用了 update_inventory() 和 send_notification(),但没有调用 process_refund()。
三分钟修好。提交,合并,测试通过,发布。完美。
第二天早上,客服电话被打爆了。不是退款问题——退款功能正常。问题是:取消订单的流程改了之后,部分用户的积分没有正常扣除,有人用多出来的积分换了礼品,礼品库存出现了负数。
你以为修了一个独立bug。实际上你触碰了一张网。
在软件系统里,一个用户下单,背后连着的可能是这样一张关系图:
订单系统 ← 支付系统 ← 库存系统 ← 供应链系统 ↓ ↓ ↓ 积分系统 ← 用户系统 ← 通知系统 ← 风控系统
改动任何一个节点,都可能影响到所有连着它的其他节点。有些影响是显性的,测试能发现;有些是隐性的,只有生产环境才会暴露。
线性思维是系统思维的死敌
人类大脑天然倾向于线性因果——A导致了B,所以修好A,B就自然好了。在简单的、机械的系统里,这个逻辑没问题。
但现代软件系统是有机的、动态的、相互耦合的。系统思维里有两个最反直觉的定律:
第一,干预一个系统最小的点,往往不是最有效的杠杆。就像那个医院,想减少用药错误,方法是增加核查项目。但核查项越多,实际执行率越低,错误反而更多。最有效的杠杆不是"增加核查项",而是"让正确的流程更容易执行"。
第二,最明显的解决方案,往往是问题的一部分。你想减少线上bug,于是加强了测试流程,测试流程长了两倍,团队压力大了两倍,工程师开始赶进度,跳过了部分边界测试,bug反而更多了。
三个真实陷阱
服务器CPU经常飙高,内存不够用。解决方案:加内存,扩大缓存。结果代码变得更慢了——因为开发者知道有更大的缓存,就不在意内存管理了,内存泄漏的代码没人急着修。半年后内存扩大三倍,性能只提升10%。
系统里出现脏数据影响报表准确性。解决方案:写更多过滤规则。报表正常了三个月,然后有人发现脏数据的源头没堵住还在持续产生,新规则又漏掉了某种新格式的脏数据,报表变成了"看起来正确但实际错误"的状态。
系统太大团队协作困难。解决方案:拆分成多个独立服务。服务拆分后,跨服务调用延迟上来了,数据一致性变得复杂,团队之间的接口协调成本超过了原来的代码合并成本。一年后又花大力气把部分服务合并回去。
这些不是虚构的场景。这些都是我在不同团队反复见到过的真实案例。
动手之前,先画一张小纸条
我不打算给你讲高深的系统动力学理论。只分享一个我自己在用的方法:
每次对系统做一个改动之前,拿一张便签纸,画四个格子:
触发事件 → 直接影响 → 连锁反应 → 最终结果
就这四步。拿取消订单那个bug来说:
触发:取消订单不退款 直接:用户没有收到退款 连锁:用户投诉,客服介入 最终:用户流失,平台损失
画完之后你会发现,退款的缺失只是链条上的一环。真正的问题是:为什么退款逻辑没有被覆盖?背后可能是测试用例没写,可能是设计文档缺失,可能是reviewer漏看了。
修一个点不够。要修的是整个链条。
还有三个问题值得在动手前问自己:
这个改动会影响到谁的使用体验?有时候一个技术改动影响的不只是代码,还有使用这个代码的人。
如果这个改动出问题了,多快能发现?好的系统设计,是改动出问题时能立刻发现,而不是三个月后在生产环境爆发。
这个改动会让谁更容易出错?那个答案,往往是整个系统里最薄弱的环节。
软件系统是一个活的生态系统。你往里面扔一个改动,它会以各种你没想到的方式生长。线性直觉告诉你A坏了修A就好,系统思维告诉你A坏了可能是因为B和C都出了问题,而B和C的问题可能来自六个月前D做的一次"看似无害的优化"。
不追踪整个链条,你永远在头痛医头。
下次修bug之前,先画一张便签。答案往往不在bug旁边,在三步之外。线性直觉告诉你A坏了修A就好,系统思维告诉你A坏了可能是因为B和C都出了问题,而B和C的问题,可能来自六个月前D做的一次"看似无害的优化"。
Python学习杂记
还在用多套工具管项目?
一个平台搞定产品、项目、质量与效能,告别整合之苦,实现全流程闭环。
白皮书上线