Let’s to be a bug-free programmer
开会时听到James提到,有一个目录被我excluded from project and pushed to Production line,我心当即一整个的碎了一地,下个迭代中“可能需要”exclude的我却因为临时在本地测试最后未将它复原而引起线上数千条exception logs和end-user投诉。在随后的数小时中我一直处于抓狂到需要不停“啊啊”大叫的状态,连带骚扰了一群人,在公车上依然是一想到就呲牙咧嘴恨不得找块豆腐当场撞过去得好。我的这种在别人眼里很奇异的状态自从加入本公司后出现过不少次,在这期间,我承受着自己施加给自己的巨大压力,从刚入公司到现在,这种对线上BUG的恐惧感始终未曾消失,甚至对自己所有BUG的自责感连连增加。
工作中,这种错误的出现一次一次成为那双踹着我去安静下来省思的无影脚,我甚至在stackoverflow上问出了How to be a zero-bug programmer? 在这样被不断要求完美而又永远不可以达到的状态下,我一次一次对错误本身着迷,对变化和改进着迷,每一次错误都意味着我有动力继续省视和回看自身,永远都没有必要满足于现状因为我还没有能触到"glass celling“,依然有成长空间。
去年6月James来武汉时,大家坐在一起聊了很多,关于如何提高编码质量、如何建立更好的沟通等,我当时曾写了一篇蛮长的文章,并且在之后在onenote下更新了important页面,写下了30来条注意事项,每一次check其实都有“尽量”做得蛮充分,比如,在“每次”check in前必定会使用beyond compare或其它diff工具与本地所取得的最近trunk来做文件夹或是单个文件的对比,并检查所有差异点,再简单的数行代码也会反复审查,但一个人的力量实施起来就是很有限,
在出现问题后,美国方的表现总让我对自己愈加惭愧,问题出现的当即,不抱怨,不表示出任何负面情绪,不责备,所做的不过是三件事:
1、如何做才能将损失降低到最小;
2、询问事情出现的原因;
3、如何避免再次出现。
但在事后,总会好好做一番总结。
让我对“如何规避粗心”作一点思考,先来找点极端的示例来做对比。比如,外科医生做阑尾手术,并在手术过程中“不小心”将棉芯遗落在病人腹中并造成之后甚至致命的严重后果。这看起来似乎是南辕北辙,不过在粗心、不规范、缺少检查等方面具有共通性。
1、手术是阶段性操作,有开及收两种临界状态,是一个阶段性过程。
在开发的过程中,保证阶段性的专注是必要的,这样能避免在这个过程中偶然突发其想的做出一些之后未能重新捕获的操作,特别是在这过程中,因以期在短期内得到反馈,故只是将注意事项移到大脑某处的临时“存储”空间而未能记录下,有时大脑这个“任务篮”有时不靠谱,在它被中断、打扰或是被其它事物突然性占据时,会出现遗漏甚至遭遇dispose(),进而造成之后难以觉察的内容细小却可能严重的问题。
有一个较流行的PROMODORO(番茄)时间管理法 (中文官方网站),是一种将任务划分为25分钟突击的时间管理法,每开始一个25分钟,期间不允许被打扰 (可参阅《时间管理圣经——番茄工作法》),结束后,可休息,再继续下一个25分钟。不过,这种以时间块划分的方法未必符合开发工作,我需要改良一下:有意识的将开发工作阶段化,大任务化为小任务,形成短时的task-based的高度集中化,临时起意的开发和没有结果的暂停,都不是好习惯。在每次开启这次iteration时,明确的问自己,这次我需要完成什么,记在本上。在高度集中下,如同一个堆栈块,不会出现临时的搬移和重新分配,空间连续性增强,出错可能性降低,就象剪切版,当前已存事物,如果再次ctrl+v,会将之前的覆盖,开发或任何工作时,尽量避免不同事务,在这个之前已定的阶段性任务到达结尾时才可以被终止、打断,或是重新开始下一个工作。这期间,任何如切换音乐、弹开QQ等,可以被尽量暂时延后。这种训练之下,相信大脑会更加容易集中,减少“粗心”的可能。
2、医生为何要将棉芯放在病人腹中?不要将材料放在病人肚子里,即使当时放进去,也要尽快在短时内取回吧。
在决定做一件“很冒险”的事前,问自己是不是必须得这样做,在这种询问下,能加强自己对它的警觉性,我不断的犯过这种问题,对有的改动看得“很小”,“一会再改回来不就得了”,“我会记得的啦”,我是很喜欢折腾的人,比如早前将global.ascx异常处理整个return掉,或是做一些有的人认为“天呐,这可一定得记下来,不然一会忘记了就惨掉了”的事,如果认为一定需要做,拿笔记下,在必须要做时,人为增加一个可捕获的检查点。即使自己已经在之前有“可能会产生问题”的疑虑,就不要放过它!更不应该让明知道会带来问题的代码或行为长时间的停留不作处理。要记得“好记性不如烂笔头”,有敏感性操作 - 比如增加test代码或操作时,拿笔记下来,划个红圈,标注下。
注意,如果你在你觉得你需要写下它时,记得去看一下,你是否当下有时间去完成它!如果它超出2分钟,记下它!如果2分钟内就可以顺手完成,当时就完成它!这“2分钟原则”也是GTD原则之一。
3、在做手术时,不能同时听音乐,护士坚决不可以吵闹以分心,不然,就算我把棉花掉进病人胃肠里,我也可能转头就忘记了。
做开发,不需要一颗不清醒的头脑、不清晰的思维、不成熟的分析、糊里糊涂的代码和操作。要做到这些,除了需要保证良好睡眠、暂时放下情绪垃圾、只着眼当下,还要在当下清除各种distractions,例如:音乐、QQ的闪动、打断等。我是属于临时性记忆堆栈空间过小的人,所以这个时候,如果一定需要做出回应,而且脑堆栈里又有事,最好花半分钟时间将它们记下来,以免它们划入冰山底层然后bite you back。,比如这个BUG中所涉及到的exclude操作,在我决定这么做时,应该给它一个结束的动作将它include回去,可在这过程中,我也许自己干扰了自己,在这种需要连贯的过程中如果出现停顿,就有可能会产生问题。
4、医生在切除阑尾的过程中,切到一半,突然看到肠壁有点脏,动手将消毒水先清理了下。
我没一点切除阑尾的概念,不过正在进行一件事时,如何被无关紧张的事情吸引住而走神,想来一定不是好事。在写代码时,会很正常的突然被某个老旧的代码分心,楞就是想做个简单的refactor,它与当前逻辑根本无关,这时,在#1提到的阶段性中,建议不应打断,可以将它们用//todo 标注下来,要时刻记得one time one thing原则,这也是wai-yin在与我开会时提过几次的问题,在当前有预期结果的计划下,不要停下,在下一次迭代中统一再做不迟。至于其它不可以写进//todo的,可以就手记在纸上,随意写在文章的某处,任何地方,不需要再建个NOTE之类,直接就地取材,笔记不在乎有多漂亮,快就等于高效。
5、做手术时,医生需要护士,并且需要做阶段性的检查如心跳、血压、呼吸等是否正常,每一步严格按事先设计好的步骤来。
人毕竟不是机器,大脑的组织千奇百怪,神经有可能突然搭错钱,可我们不能可以说,出了错是正常,我们有太多方法可以规避它。所以“规避”,就是使用规则去避免不利情形的产生,比如,
- 医生需要护士,程序员需要tester和code review,或pair programming;
- 阶段性的检查,在一个有完整开始结束状态的过程后,做一个检查,清除之前的注意事项,不让它一直appending下去;
- 使用明确的check list或test case或是在开始之前做的plan,都可以是规避的一种,有的test-first,impact analysis,再大一点的就是design doc,以及code analysis tool,都可以做到“规避” 。
很多时候,我们会说“人一懒”就忽视了这些,而错误和我之后一些“啊啊啊”的状况,从我的实际经验来看,我的大部分问题都不是代码问题,而是归结于“当时人一懒”“忘记记下了”,“以为不会有事的啦”等懒、自以为是或是侥幸心理,不管做任何事,这些都是要不得的。
6、手术成功了,结果又“临时起意”做了病人不需要的或是事先没有确认的事,犯了严重错误。
在写代码时,因为看到其它旧的代码并不好看,你一时“好心”的去“改正”它,又并没有通知其它人知晓,你一个人用着“应该没有问题吧,我觉得还蛮straightforward”的态度,最后“好心办坏事”的情况,对我来说也是屡见不鲜了。这世界上不止怕坏人,也怕蠢人 - 怕蠢人好心办坏事,不自省下次还要接着犯并自以为自己正确的。
在敏捷团队中,就比如crum,需要一个ScrumMaster充当相当于PM的角色;需要一个ProductMaster,他需要通过与客户的沟通并从客户角度来分析问题,定制优先极、确认需求,确定解决方案,并按照当前sprint的quote来决定backlog;team member,执行者,负责实现功能、保证deliver working software。明确的知道不同角色的职能区别,善于主动沟通、保持团队透明是敏捷团队的基础。即便是我坚持认为这样更好,也需要与BA做沟通,更别谈,任何一点改动都必须对BA透明,不管从测试、support等,都是必须的。
7、借助工具,做足检查。
“多检查”事实证明,其实是没有什么作用的,检查多不代表有效,有效的也不需要“反复”检查,写下Check list,总结过程中产生的注意事项笔记,更新test-case等,都是方法在敏捷开发中,错误的产生,多半是出于在破坏其它与任务无关的部分而产生的,所以test-first和TDD,是需要的。各种diff工具,和sandbox也可以降低失误率。。test-fest是需要训练的,我也准备为之努力。
还有很多需要反省,希望自己能以谨慎、科学的态度来看待coding和相关工作,做一个真正能够self-directed、自管理自成长的开发人员!
自己的博客同步:http://www.allimilla.com/2011/03/lets-be-a-bug-free-programmer/