一、什么是墨菲定律?
墨菲定律是一种心理学效应,由爱德华·墨菲(Edward A. Murphy)提出的,亦称墨菲法则、墨菲定理。
墨菲定律的原句是:“ If there are two or more ways to do something, and one of those ways can result in a catastrophe, then someone will do it.”(如果有两种选择,其中一种将导致灾难,则必定有人会做出这种选择)。墨菲定律的根本内容是:如果事情有变坏的可能,不管这种可能性有多小,它总会发生。
二、产生条件
在数理统计中,有一条重要的统计规律:假设某意外事件在一次实验(活动)中发生的概率为p(p>0),则在n次实验(活动)中至少有一次发生的概率为 P=1-(1-p)^n。由此可见,无论概率p多么小(即小概率事件),当n越来越大时,P越来越接近1。
这一结论被爱德华·墨菲应用于安全管理,他指出:做任何一件事情,如果客观上存在着一种错误的做法,或者存在着发生某种事故的可能性,不管发生的可能性有多小,当重复去做这件事时,事故总会在某一时刻发生。也就是说,只要发生事故的可能性存在,不管可能性多么小,这个事故迟早会发生的。
三、具体内容
如果把这个定律展开说的话,它其实只包括4句话:
1、任何事都没有表面看起来那么简单。这句话告诉我们任何事需要自己分析和研究,考虑周全,未雨绸缪。
2、所有的事都会比你预计的时间长。时间貌似永远不够,提前收拾好早点赶高铁。
3、会出错的事总会出错。任何一件事只有三种结局:变好、变坏或保持不变,尽最大努力,做最坏的打算。
4、如果你担心某种情况发生,那么它就更有可能发生。这其实是一种心理效应。
四、软件测试与墨菲定律
软件的 bug、缺陷、漏洞,这是永远不可能杜绝的 。被人们看到的漏洞往往很低级,但考虑到软件产品的复杂度,以及开发进度、需求变更等客观情况,漏洞也并不是想象中那么容易避免。就在半个月前,知名民宿平台 Airbnb 就爆出过类似的大 bug:当你支付房费的时候, 如果切换货币,价格并没有跟着变 。你可以拿2000越南盾支付原价2000欧元的民宿。在计算机史上,类似的问题数不胜数,举几个知名例子:
- 1994年,英特尔的奔腾CPU芯片被曝出缺陷: 会在精度要求很高的数学计算上出现问题 ,比如 (4195835/3145727)*3145727-4195835 这样的结果计算出来不为 0。最后英特尔为此付出 4 亿多美元更换芯片 。就在大约一年前,英特尔的另一个芯片漏洞也波及了市面上绝大多数的电脑、手机和云服务器,这个我去年有文章科普过:关于这波IntelCPU漏洞,我见过最形象易懂的解释
- 1999年,美国航天局的 火星极地登陆器在着陆时失联 。后经调查认定,故障原因很可能是一个 决定关闭推进器的数据位设置逻辑有误 。
- 1991年海湾战争中,美国的 爱国者导弹防御系统失效 ,未能成功拦截导弹致 28名美军士兵被炸死 。原因经分析后,是因为 系统时钟数据精度不够 ,存在微小误差,长时间运行后误差积累放大,在拦截过程中可能引起数百米的偏差。
- 千年虫问题 :上世纪早期的软件开发者为了节省空间, 使用两位数记录年份 。然而到2000年时,一些软件仍在使用,使得99年之后变成00年,引发异常。有人估计全球为此花费的相关费用有 数亿美元 。
由此看来,程序员还真是一个高危职业,一不小心就可能造成巨大损失。 如果你没有生产过严重的 bug,可能是你运气真的好,但更可能是你代码写得还不够多。 对此我自己也是不少血泪教训。那面对难以避免的 bug,开发者应该怎么办呢?建议:
1、重视软件测试
正因为漏洞的普遍存在,以及可能带来的潜在损失,所以软件测试是即为必要的。除了需要有专门的测试人员把关,每个合格的开发者也应该是一个合格的测试者,正如有句话说的: 一个优秀的程序员就是那种即使是过单行道都要往两边看的人 (Doug Linder)。对于自己写出的代码,你自己是最了解的人。在开发早期就做好 单元测试 ,可以大大提升程序的稳定性,降低后期测试的成本。当你写的每个函数都通过单元测试,成为一个功能模块时,再进行 集成测试 ;最后对整个完成的产品进行 系统测试 。
企业更是应当重视软件测试的必要性,如果只追求功能快速迭代,拼命赶进度,最后有可能得不偿失。因为 bug 或操作失误导致企业破产的例子也不鲜见。
测试的方式一般分为 黑盒测试 和 白盒测试 。上面说的开发者自测一般是白盒测试,即你对代码的实现逻辑是已知的。白盒测试在选取测试用例时,讲究对 代码逻辑的覆盖 ,即你选用的测试数据要能保证让每一行代码每一个条件都被执行到,尤其是一些 边界条件 。而黑盒测试是指不考虑代码逻辑,仅关注程序的功能和输入输出。软件发布测试版让用户使用,就属于一种黑盒测试。在黑盒测试时,讲究对 等价类的覆盖 ,通俗地讲就是覆盖到所有可能发生的情况,包括正常的和不正常的,同样要注意边界。
我们 码上行动 有个期中项目,就是对教程中“猜数字”游戏的扩展,增加多次游戏的功能。看似简单的功能,实现起来不难,但几乎大部分同学提交的代码都会存在一定的缺陷。这就是由于编程新手缺乏测试的意识和方法,一般只会按照自己的设想输入,发现结果对了就认为大功告成。其实不然,你得考虑用户如果猜的数字超过范围怎么办?输入了小数怎么办?输入空白怎么办?输入了字符怎么办?……
2、相信墨菲定律
墨菲定律:如果你担心某种情况发生,那么它就更有可能发生。
测试做得再好,也只能是减小 bug 的概率。作为一个开发者,你还是要认清现实,做好最坏的打算。
- 如果你要上线新功能,那很可能导致宕机
- 如果你要更新数据库,那很可能会丢失数据
- 如果你没有检查备份,那很可能它就恢复不了
- 如果你搞一个促销活动,那很可能会被羊毛党撸死
- 如果系统出现了漏洞,那很可能是在半夜
- ……
但真当你意识到这些绝望的时候,反倒可以提前做好应急预案,将损失限制在最小。如果拼多多在设置出100元无门槛券的时候就相当虎视眈眈的黑产羊毛党,可能事情就不会这样。不过也许现在就是他们的应急预案也说不定呢:控制损失的同时还赚了一大波曝光。世事难料啊!换个角度,能造成巨大损失也是一种幸运。
另一方面墨菲定律也反映了一切问题都是可以解决的。
无论是怎样的困难和挑战,我们总能找到一种办法或模式战而胜之。