所属文章系列及序号:寻找尘封的银弹:bug修理厂(二)
当我们经过本系列上一篇文章的洗礼之后,又有一座山峰需要攀登:这是不是一个bug。
这又是一个看似简单的问题。
有时最简单的问题,最容易被人忽略。有一次,我遇到一个很奇怪的bug,因为无法重现,所以我就只能通过看日志文件来寻找线索。看着看着,我发现那个日志的内容,并不是最新代码写进去的,那一瞬间,我明白了:用户很可能是使用了错误的安装包!于是我就按照这个思路去排查发给用户的安装包,果然是发错了。我再用旧的安装包测试,不出所料地重现了那个bug,这从侧面映证了发错安装包的错误。
所以就得出了第一条原则:排查用户的安装包。
【不是bug的情况】
这里列举一下“不是bug”的情况:
一、排查用户的安装包,如上文所述。
二、排查是不是用户的环境配置出现了问题,说起来,这算是“技术支持”该做的事情,不过有时还是有些bug是“技术支持”忽略的,有时甚至是需要代码背景才能洞察到是环境配置出了问题。
三、用户用错的情况:例如用户必须先点击“编辑”按钮才能开始编辑界面上的数据。
四、说明书里没有提到,但属于常识的情况:例如用手指点击手机屏幕时不能沾水,又如手机操作系统有时会自动重启。
五、上面这些还算容易理解,不过下面这条隐秘常识,会把很多人绕进去:例如某公共场所公告里写着“禁止随地吐痰”。可能有人会在这里扔矿泉水瓶,他会直觉地认为“这里只是不允许吐痰,但没说不允许扔垃圾”。
而“禁止随地吐痰”意味着保持环境清洁,“禁止扔垃圾”应该在这个范围内,再进一步说,“随地大小便”更是要禁止的。类似的情况很多,它们都属于一类,就算能穷举完全,让人看了流水账式的长长列表之后,只想抓狂,谁还有心情去记住这些内容,所以最好的方式是只写一条。这也解释了,2000多年前,刘邦带兵攻占秦朝首都咸阳之后,只与民“约法三章”而民心悦服的原因。而这就是隐秘常识。
这里我们展开一下:科学思维也好,哲学思维也好,大体上是想把问题的所有方面都展现在表面上,让大家都可以讨论,我们从小就是学着这套理论长大的。而真实的世界是复杂的,不可能穷举所有的情况,所以我们要时刻关注自己的思维方式,不能死扣那个“表面上”的道理。其实,世界上一直都存在这样一种思想:
最关键的成功决策,往往都是科学和哲学无法解释的!
就像前文提到的“隐秘常识”,它符合哪条科学原理?就算符合,之后它就变成了一条“定律”,时间长了,“定律”多到没有人能记得全。当“定律”的数量堪比地球上沙子数量时,满载着这种数量级“定律”的科学之船,还如何在时空中继续航行?
对于判断“是不是bug”来说,情况是无穷无尽的,我们能做的就是让自己保持一颗突破惯性思维的心、一颗突破舒适区的心!
【是bug的情况】
“是bug”的情况中,又分为两类:不可修复、可修复。
一、不可修复:一般都是由于系统限制而不可修复。
有时,这些限制会变成可修复的,因为系统架构有所变化,原来无法修复而现在可以修复了,也可能因为换了一个开发者而找到了解决方案。
我曾经发现过一个很奇特的情况:在Oracle数据库客户端中输入一条SQL,如果结尾是随意输入的字符串,例如“select * from t1 abc;”,令人大吃一惊的是,Oracle居然不报错,而返回结果!
我觉得对于这种情况,Oracle是不会写入系统限制文档的。关于这个现象,我没有看到任何文档里提到过它。不过据我的研究,很多数据库都使用lex和yacc作为词法和语法解析器,而yacc有一个预取一个token的机制,预取之后的那个token,最后找不到匹配值,就直接忽略而不报错。
这种情况也许可以算作“不必修复”。
二、可修复:再次分为“是bug”,或“是需求”。
区分出Bug或需求并不难:说明书已经告诉用户,在某种情况下,做某种操作,一定会有某种结果,而实际结果和期望结果不相符,这是bug。而需求是:说明书没有告诉用户,而用户想要的一个功能。
难点在于,必须判断出:需求是不是符合模型、需求是不是符合产品方向。
需求是不是符合模型:我们开一个脑洞,假设人力资源不受限制,全世界的开发者一起做这个需求,这个需求能不能做出来?这要是再做不出来,一般都是在逻辑上自相矛盾的情况。这种情况我遇到过,但是很难通过一篇文章描述出来,此处我只举一个简单的例子,例如用户想让系统支持1+1=3。作为开发者,只需知道有“需求不符合模型”这种情况即可,遇到具体问题的时候再具体分析。
需求是不是符合产品方向:具体来说,就是与现有系统是否兼容,与产品发展方向是否兼容。例如:用户想在某一个界面中采取独特的显示风格,通过查看代码发现:这个界面会被多处复用,新做一个是可以,但会导致产品多个功能相关界面风格不一致,所以作为产品策略可以委婉拒绝。
至于现有团队能不能实现它,是属于较低层次的问题,我会在后续文章中讨论。
作于2018-3-25