为什么开发人员不能触碰那些棘手的业务参数,无论何时?
摘要:你好呀,我是歪歪。 前几天发了一个牢骚: 本来只是单纯的吐槽一下,但是好多人对其中的细节比较感兴趣。 大家都是搞技术的嘛,对于“踩 BUG”这种喜闻乐见的事情,有兴趣是很正常的。 其实我这个 BUG,其实严格意义上不能叫做 BUG,因为和程
你好呀,我是歪歪。
前几天发了一个牢骚:
本来只是单纯的吐槽一下,但是好多人对其中的细节比较感兴趣。
大家都是搞技术的嘛,对于“踩 BUG”这种喜闻乐见的事情,有兴趣是很正常的。
其实我这个 BUG,其实严格意义上不能叫做 BUG,因为和程序无关,甚至和技术的关系都不算大。从标题上你也能猜出来,是和一个业务参数相关。
但是在这个过程中,因为我是整个事件全程的亲历者,所以现在回看这个事情,我还是有一些思考在里面的。
我觉得这是一个程序员会遇到的“典型事件”。
那就用这篇文章一起复盘一下吧。
背景
要说明这个问题的背景,甚至不需要一个具体的业务场景,只需要围绕着以下这个非常常见的利息计算公式,就可以说明问题的起因:
利息=计息金额*日利率。
日利率=年利率/360
由于日利率的计算,涉及到除法,在对应需求第一次开发时,业务的要求是日利率保存 7 位小数。
在程序中,年利率和日利率是两个字段分别保存的,日利率在初始化的时候就算好落库了,后续程序直接取这个算好的日利率就行了。
系统上线,相安无事。
跑了一段时间后,业务又提来一个需求:当前的精度不够,需要调整到 11 为小数。
你不用好奇歪师傅这边到底是什么业务场景,反正我去看了业务数据,需求是合理的,那就把需求接过来干就行了。
保存 7 位小数和 11 位小数,大家都是搞开发的,肯定也知道这个就是一个小改动,很快就能搞定。
事实也是如此,虽然之前的需求对应的代码不是我写的,但是我看过代码,清楚的知道改动点在哪,所以很快就开发完成。
前面说了,这个需求之前在线上按照 7 位小数跑了一段时间,所以存在一些存量配置。
针对这些存量数据,在需求评审会议上的时候,我提了一句:存量配置怎么处理呢?
业务答复:这次需求上线的时候,你按照 11 位小数重新算好,然后写 SQL 更新一下就行。
我心里一盘算:计算公式明确,年利率我也有,算一把,没啥问题。
就答应了。
然后,不出意外的出意外了。
假设年利率是 2.5%,除以 360 之后,保留 11 位小数,应该是 0.00006944444。
而我不知道当时为什么手抖了,在 SQL 里面写成了 0.00069444444。
我给你对比一下:
0.00006944444
0.00069444444
相当于我写出来的日利率被扩大了十倍。
然后再回头看看这个公式:
利息=计息金额*日利率
日利率被扩大十倍,那么对应的计提金额也会被扩大十倍。
这就是问题的背景。
一个单纯的人为失误,和程序没有任何关系,所以严格意义上不属于程序 BUG。
但是这个问题确实是足够低级。
为什么没被发现?
那么这个错误的 SQL 是怎么通过代码评审、测试验证这两道关卡被带到生产环节的呢?
首先,这一次提交的代码,压根就没有评审环节。
我有代码提交权限,也有代码审核权限。所以我自己提交,自己就审核通过了。
其实这个需求应该是组里面另外一个小伙伴来做,但是当时他被调到其他组了。
他还在我们组的时候,我们的合作模式是他提交代码,我进行审核。
如果有这个环节,我觉得我有 50% 的几率发现问题。
为什么是 50% 呢?
因为这取决于我审核代码时是否有正在处理其他的事情,如果有其他事情处理,我可能会形式主义的看上几眼。如果没有其他事情,而这次提交的代码量又不大的话,我基本上都会认真的过一下提交的内容。
通过代码评审之后,接下来就应该是测试环节。
测试主要关注的是精度从 7 位变成 11 位之后,最终计算出来的利息是否符合预期。
他测试时是走了整个业务的全流程。
在“全流程”中,这个 11 位精度的日利率,是在页面配置年利率的时候通过程序自动计算出来的,不会错的。
而他在验证 SQL 语句的时候,测试环境又没有生产环境的配置,所以他拿着我提供的 SQL,只能保证写的语法没问题,能正常执行,并不能确保里面数据的正确性。
而我也记得很清楚,我当时给他说过:你执行一下 SQL 不报错就行,值的正确性,我来保证。
而且戏剧性的是,测试同事很仔细的去看了值,他去数了确实是 11 位小数。但是可惜,站在他的视角,他发现不了值被扩大了十倍。
所以,测试环节也没有发现这个问题:
0.00006944444
0.00069444444
就带着上生产了。
一个问题正常来说不应该被带上生产,但是我们确实不能保证测试环节一定能把所有问题都测出来,所以新项目、新迭代的生产验证也是非常有必要的。
这个我们也做了。
按理来说,生产上的数据已经是错误的了,而且是一个“利息金额扩大十倍”的明显的错误,如果主动去做了数据验证,应该能被发现才对。
