我曾经在一家卖广告的地方工作。这家公司想要的其中一件事就是让员工尝试一下,看看自己实际使用广告产品是什么感觉。这是您有时会听到的常见的“dogfooding”事情。
为此,他们每月发放 250 美元的信用额度。您只需转到某个内部网页并单击一个按钮,它就会记入您的帐户。每次日历滚动到新的月份时,您都可以再次单击它。
他们在我们第一天或第二天的课程中告诉了我们所有这一切 – 地狱般的“入职”。在此期间我注意到一件事:我们的主持人还没有声称他们的功劳,所以他们就在我们面前真正做到了。他们去加载页面,但它被炸毁了——代码中的某些东西爆炸了,它没有工作。他们重新加载它,然后它开始工作,现在他们的帐户中有 250 美元的虚拟广告资金。
几周后,新的一个月开始了,我想进去试一试。我去启动它,它爆炸了,就像我班上发生的那样。但是,嘿,这一次我有了自己的电脑,可以访问源代码,甚至还有一点点前端经验,这是由于他们分配给新员工的一些介绍性任务。为什么不尝试一下呢?这个地方应该是关于修复随机的东西,即使它“不是你的”——至少到处都是“没有什么是别人的问题”的海报暗示了这一点。
我将它加载到我的开发环境中并开始破解。果然有问题,第一次通过,就炸了。这有点愚蠢,就像代码抛出异常,但异常处理路径进行了错误的日志调用,这样会破坏整个请求。我修复了日志记录,这样我们就可以真正看到异常是什么,这样我们就有机会解决任何真正的问题。很简单,对吧?我将更改发送给最后一个触摸代码的人……那天早上刚刚触摸它的人,很奇怪。他们感谢我,它被应用了。
然后我试图获得我的信任,这次它又爆炸了,但现在它记录了错误的地方。我可以在开发环境中看到这一点。这是关于使用错误数量的参数调用某些函数。
代码本身做了这样的事情:
if (条件) old_func(a, b, c, d, e) else new_func(a, b, c, d, e);
问题是 new_func 没有接受 5 个参数。花了 4。我通读了代码,发现它不再需要“d”参数,所以我只是将 arg 列表更改为 (a, b, c, e)。我认为这是刚刚更改它的人的一个简单疏忽。
然后我自己运行它,单击按钮,收到“您的信用现在在您的帐户中”的消息,我很高兴。我让一个朋友也试了一下,结果对他们也很有效。
原来这个 if-then-else 部分是那天早上添加的,所以我再次将代码发送给那个人审查,他们再次感谢我并接受了它。我去做其他非前端的事情,稍后代码传到了内部 Web 服务器。
几个小时后,有人在网上伸出援手:我们必须关闭广告信用这件事。它放弃了太多的钱。多少钱?两万五千美元。 25,000 美元。不是 250 美元。
发生了什么?它一直将信用金额作为便士传递给“old_func”,所以它传递了 25000,因为 25000 便士实际上是 250 美元。但是…… new_func 拿了美元,而不是便士。因此,在这种情况下,25000 是 25,000 美元!
我在公司呆了大约六个星期,更改了一行源代码以修复错误(日志记录),发现另一个错误(错误的参数计数),启用另一个错误(错误的单位和零类型安全)任何点击的人都会获得价值 25 美元的有趣金钱!我点击了!我有一个朋友可以点击!而且其他人也收到了!
发生了什么?他们只是关闭了该功能,直到他们可以修复它。我们这些账户信用过多的人关闭了我们的广告,以免实际消耗任何“劣币”,并一直关闭,直到他们将其从我们的账户中撤回。然后我们就清楚地回到了 dogfooding。
不,没有人因此被解雇。
这也是为什么我说裸数字在足够复杂的系统中可能是毒药的另一个原因。如果该函数需要一个名为“dollars”的类型,而调用者有另一个名为“pennies”的类型,它就不会通过类型检查器/编译器。但是,这是在那些日子之前,所以它顺利通过了。