当系统缺少真实数据时,是编造一个看似合理的默认值,还是直接报错?这三种选择之间的差别,正是同一类错误差点毁掉三个系统、却被几乎所有人都忽略的原因。故事从一个根本不存在的数字“1.9%”开始。
一个广告实验引擎的测试单元,从未在真实场景里展示过哪怕一次,但它的产品后台却赫然显示基线转化率是 1.9%。数据表空空如也,代码却冷静地取了一个硬编码的默认值,把这个凭空出现的百分比穿上西装推向了决策链路。乍看只是展示层面的瑕疵,实则不然。1.9% 这个数值会被直接输入实验时长估算公式,用来计算至少需要多少样本才能让结论可信。如果基线是虚构的,公式要求的样本量就可能在两种方向上偏离真实需求二十倍:要么把早已合格的实验继续跑了数周,要么在噪声中草草宣布“胜者”。测试在第一条曝光之前就已经死了,而仪表盘从头到尾都显得无比健康。
这里面真正致命的地方不是错误本身,而是一个看似合理的数字比一个明确的错误更难被发现。程序崩溃,当天就能拿到故障单;但一个编造出来的数字看起来一点儿也不像“编造”的,它可能在下个季度复盘时才会偶尔被翻出来,甚至永远不会。当系统对现实毫无把握时,诚实的方式不是找一个平均值来填补空白,而是用一种机器能识别的方式来拒绝——抛出错误、转入待定状态、建立一个新的分类,总之不能是一个看起来像模像样的默认值。
修复方案并不是换一个更精确的默认值。因为当底层数据表为空时,根本没有真相可以去逼近。广告实验引擎的那一个接口现在直接返回 HTTP 400 错误码:传一条真实的基线来,否则实验就不启动。这次修改把“拒绝”这个动作从开发者一时的小心翼翼,搬进了接口契约里,系统再也没机会把假数当真的用。
相同的病因随后出现在了另外两个和广告科技毫无关系的业务里,唯一的交集就是同一个人在回溯。
在一个面向 Medicare 远程患者监测的报销引擎中,支付方资格校验原本被当作发起理赔的硬闸门。但因为产品责任边界的设计,诊所的账单员自己拥有核实资格的权限和工具,我的引擎并不掌握那一端的真值。在此前设计中,引擎要么拦下理赔、充当并不该由它来当的判断者,要么直接放行,两者都是猜。改动之后,资格校验不再是一道“通过/拦截”的闸门,而变成一个路由动作:这些理赔被送往一个名为 BILLER_DETERMINED 的明确状态——在数据模式里划出一块给真正握有信息的人来接手的区域,而不是用引擎去替他作出决定。
拒单分类引擎的问题更加隐蔽,也更贵。患者自付额、共同保险、共付额这几类拒单(PR-1、PR-2、PR-3),本质上并不是真正的“拒付”,只是应付账款从保险方转移到了患者身上。但原来的分类体系里根本没有对应的桶,于是系统里一条粗暴的规则将“非真实拒单”映射成了“无需处理,直接勾销”。引擎就这样安静地告诉账单员把患者确实欠的债一笔勾销。这次的修复也不是换一条更聪明的提示,而是在分类体系中补上一个新类别:bill_patient。在包含 30 个案例的金标准测试集上,分类准确率从 83.3% 直接提升到了 90.0%,仅仅因为现实不再被硬塞进错误的抽屉。同一个推送版本还为每条推荐锚定了基于单个服务代码的标准动作层,让映射动作的准确率从 36.7% 一起跳升到 76.7%。
这三个场景的共通教训并不是“默认值不好,换一个更好的”,而是当系统对某一件事根本没有真相时,必须用一种可以被系统自身识别和处理的方式说出“我回答不了”。无论是跳一个 400 错误、引入一个新的路由状态,还是在分类体系里增加一个真正匹配的类别,都是在对机器说真话。一个看起来合理的默认值会安静地腐蚀决策链,而要发现它,常常需要等到足够多的事实被不知不觉地改写之后。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.