n个小时的核磁扫描,n*000+RMB的实验费用,几位老师和我无数次的讨论、撰写和思考,因为一行代码的错误,毫无声息地消耗掉了。
为了最大限度地避免这种事情再次发生,我决定从自己的经历总结一下实验程序中容易出错的地方和预防方法(欢迎大佬补充指摘)。
原因分类
临时快速修改引发的bug
在现场讨论的时候,老板/其他老师突然有一个想法,只需要改动一两句话,甚至只需要改动一两个参数就能实现;对于代码有自信的同学一般就会花个数分钟把需求搞定。
但是这个其实是有风险的,如果代码之间的依赖关系没有考虑到,有可能出现牵一发而动全身的情况;整个实验刺激变形了不可怕,很容易就debug掉来;可怕的是看不出来的语义bug。
我这次的失误就是将存在A变换的a物体、B变换的b物体的实验刺激改成只具有其中之一的实验刺激,一激动就改出了一个四不像,出现了存在A变换的a物体和存在A变换的b物体两种刺激。
可怕的就是,由于我们实验的重点在于{A,B}相对于{C,D}的差别,所以我和看过刺激的老师们都没有看出来b物体被施加了错误的变换,核磁就这样做下去了,数据就这样分析了……
代码庞大、组织混乱引发的bug
我们组有个大神前辈写了一套呈现实验刺激的代码,将实验刺激的设置、实现和实验流程的执行分别放在了不同的文件里,这样有助于读者的理解,也方便了单元测试和修改。有了这套代码(听起来更像类似游戏引擎的实验引擎),修改实验的时候不用每次都在实验流程、设备参数上花费太多精力。
这套代码写得很整齐,也很方便改;不过我改了一次、两次、三次之后,有时候会变成同一常量不同位置重复赋值、或者某一条件下会发生重复赋值的情况。
这是我这次项目中的另一个bug,幸好跟老板讨论后发现它帮我们歪打正着了一个看起来比较好的实验刺激。
没有仔细测试就上线/没有仔细核对而忽略的bug
上述两个bug能够活到正式实验的原因是我没有对新加的代码用心的整合和单独测试,也没有换另外的算法进行检验。最大的教训是:发现了一个bug是由于没有进行过单独测试而产生的时候,就应该暂停执行,对整体代码的更新部分进行检查和测试。 我这次其实是先发现的后边的那个bug,但是我急于做实验而且出于害怕(对实验是没有益处的)没有跟老板讲,错过了全盘复查的机会;后来实验数据收差不多的时候,在筹备下一步实验的时候,因为小bug的存在、为了谨慎起见我重读了我改过的全部代码——结果如上所述,这个大bug让我头嗡了一个小时。
简单列一下解决办法
修改的代码,要分模块进行测试(新加的不同属性单独核对),用不同的算法进行验证(正视图的实验刺激画一个俯视图看看物体排放是否合乎预期,屏幕上画出的图像的实际尺寸是否符合投影的原理),用极端值检验是否出现异常(动态的刺激是否动起来就会丧失某种设定)。
明天(今天)要把改好的程序好好测试一下
为了保证效率(这个词真的很危险,,),我打算用类似脑图之类的工具把我修改过的函数都列出来,逐个想一想:1. 是否做过逐行检查;2. 包含几个部分,每个部分是否可以单独测试,是否可以用另外的算法检验;3. 函数和其它函数的对接是否需要检验测试。
然后做个测试,写一个简易的测试报告发给不太会写程序的同时,问问他我这样测是否有漏洞。
这几千块的经费不能白花,一定得留个靠得住的bug最小化流程~hoia
更新
10个减少bug的小贴士 Quality Begins With Code: 10 Ways to Reduce Software Bugs - Simple Programmer