倒上茶水一杯,看着这个主体《我修复的印象最深的一个bug》,顿时陷入长久思绪当中。自从业十多年以来,写过的代码无数。当然,属于自己挖坑自己填的bug也修复过,捣鼓祖传代码的bug也修复过,在修复bug的同时给后人挖坑的事也没有少干过。具体有多少,可能无法用数字来衡量,不知道有多少的bug被close或者从close到reopen再到close.
如果非要说修复的印象最深的一个bug, 那可能是大约10年前的一次事故Bug. 当时我们负责给某工厂的生产系统上线BOM生产系统。产品生产前,各个零件的组合方式以及属性选择全部通过我们提供的业务系统进行统一编排。编排审批完成后,将会有打印机将各种生产表单分发到各个生产岗位进行生产。当时的我和另外一位同事所在的小组,负责了某一个模块的开发,当时也不像现在的前后端分离,基本就是谁负责一个模块,谁从头到底进行开发,会从从Model,Controller,View 一条龙服务到底。
当时模块当中有一个表单里面有一个关键指标的下拉框,用户可以通过选择“是/否”来设定其属性。当开发完成后,提交测试也完成测试,再到上线,交付使用。一切看起来就想日常片段一样的索然无谓和自然,无非就是一个简单表单的CURD,真的是too sample。
然而,在交付后的第二周,收到工厂侧传来一条内部的通报通知。厂家的某位员工因为在创建生产计划表单时,因为关键指标选择错误,而导致一批产品报废,造成了严重的生产事故。而在整个系统的审核人员也受到相应的通报批评。因为平时和业务部门的人还比较熟,这2位收到通报的伙伴还在和我吐槽,创建表单的人说的百分之百选择的选项是 “否”;审核表单的人也打保票的说审核时,选项看到的绝对是“否”,但是为什么最后在生产指令打印到生产岗位时,显示的选项为“是”,他们也觉得无法相信,最终只能认为是同时走神造成的。听到此处的我当时还觉得居然有如此不可思议的事情发生,在替他们惋惜过后,直觉告诉我,肯定是程序哪里有问题。
随即,打开VS Stidou2010(当时使用的一个IDE),开始分析涉及到该关联字段的页面(.aspx)和逻辑文件(.aspx.cs),并且通过在测试环境结合数据库进行排查。最终,发现了问题的所在,原来在创建/修改页面的选项“是/否” 所对应的值是 0/1, 审核页面的选项“是/否” 所对应的值是 0/1。 然而在最终的生产指令打印文件的逻辑当中,对于选项“是/否”的对应值为 1/0。所以,这也能解释为什么创建人和审核人看到的都是“否”, 然而生产岗位看到的数据为 “是”了。随机马上发起一个 hot fix 将代码修改合并,等待下一次迭代窗口期。
果真,在迭代后的不久,第二次生产计划又在同样的表单下进行创建。之前的2位伙伴此时同样按照之前的选项进行选择,并相互确认,并找其他人一起验证了他们在系统上的选项。最终,这次的生产指令没有出错。看到这个结果,之前的2位伙伴更加坚定了上一次的失误是他们自己选错了。(我们的版本发布后,普通用户只会知道我们更新了哪些功能,并不知道具体的内容。就如现在知名APP的更新日志只会写上“更新了某些功能,优化了某些XXX”一样)。
至此,该bug成功被解决掉了。我们开发组也受到了相应的处罚。但是这个bug的故事却一直让我记忆很深刻。印象最深的bug,修复并不是修复了多么大的一个系统,并不是个人的能力多么牛逼解决了一堆人不能解决的问题。我想,对于我而言,这个bug让我印象深刻,原因有三。
其一,作为开发人员搞出来的,对用户造成了一定的损失,而且还让用户打心里的认为是其自身失误造成,这一点就心里过不去。
其二,就是由于这个Bug的原因真的很简单,没有多么高深的技术。然而他就是错了,还造成了损失。
其三,是自事故之后对自身的思考,为什么会出现这种问题?说100%写代码不出问题,那是不可能的,但是如何保证尽量少出这种错误?
第三个原因是这么多年一直在不断提醒我的,如果在当时所有的事情做到了下面几个步骤。约莫也不会有那次事故了吧。
- 对于Key/Value 的约定,在团队一定需要有一个约定俗成的规矩,并在团队每个人心里。最好意思就是字面意思,比如isDelete => yes/ no , 每个人看到这个,能想到的对应值就应该是1/0 。 可见定义的重要性,特别是深入人心的职业性定义。
- 如果还在从事前端页面的开发, 对于功能的验证一定不能仅仅局限于页面上显示的。因为页面上显示的不一定是最终存储的数据。强烈建议如果还在做前端的同学,一定要去数据库里面二次验证自己的数据。
- 测试的流程完整性,还是提倡一条龙服务,不能门前雪各自扫,如果某个功能是你做的,那测试应该最好覆盖到整个流程。切记不能整体流程出错时,甩出一句“我这里是好的”,“他给我的就是这样的数据”。开发好的功能,一定要向前,向后进行测试。
- 不怕流氓怕武术,就怕开发会业务。当完成一个功能的时候,是否能够站在业务的角度和场景去验证功能是否正常,也是非常重要的。
这便是我修复的印象最深的一个bug,可能他并不是一个负载很高的系统,可能他不是用了很牛逼的技术。但是这个bug却带给我了扪心一问。
“我们写程序的,应该把自己当成一个工匠,去雕刻我们自己编写的程序。对于任何一行代码都应该当成是一个可以把玩,推敲的工艺品。”