
有这么一个场景:
一位穿白大褂的医生脸色凝重地走进ICU(重症监护室),对躺在病床上的70岁老人的家属说:太太,CT显示您先生大脑里有一恶性肿瘤,不过这个恶心肿瘤现在是可以通过手术来完全移除的。
太太:那好啊,什么时候安排手术?
医生:不过。。您先生岁数太大,身体机能无法承受手术中的创伤。虽然手术可以完全移除肿瘤,但是只怕先生挺不到手术结束了。
太太:那怎么办?
医生:那就保守疗法,将就活着呗,直到自然死亡。虽然会有痛苦和随时死亡的风险,但是比在马上的手术中死亡要好。
太太:……
与此同时。。。
一位穿着衬衫的高级软件工程师脸色凝重地走进办公室,对底下的工程师说:你的代码在项目结束前的Code Review(代码评审)中发现一个严重的性能瓶颈风险,现在体现不出来,但是在客户那边数据到达一个数量级就会体现出来了。。还好我已经有解决方案了。
工程师:那好啊,现在开始改?
高级工程师:现在来不及了,项目已经接近尾声。这个项目必须在明天提交客户上线,现在做出如此多的变动风险太大。
工程师:那怎么办?
高级工程师:先发给客户呗,在Release notes里面写清楚风险。随后我们开始做软件更新,然后再发个Patch过去。不过这段时间成本客户是不会给钱的,而且客户满意度会因为这个patch下降。
工程师:……
上面的两个场景有一个共同的尴尬:有一个解决问题的方案,但是因为时间(或者岁数)的关系来不及执行下去。
引发这种尴尬的核心原因是:发现问题太晚,总是在deadline前后发现。
项目背景介绍:
一个团队有4个项目组,每个项目组负责不同的项目,甚至有的项目组是daily deliverable。换句话说,4个项目组每天都很忙,其次是每个项目组不知道其他项目组项目的细节。
公司的SQA制定了流程有Peer Review(同事之间互相看代码)以及FTR(Formal Technical Review,正式的Code Review)。Peer Review一直没被很好的执行:
第一,没有正式的写入流程框图,给成员感觉只是“建议”(Rec.)级别;
第二,其他项目组成员不太熟悉本项目的细节,觉得看得效果不大;
第三,本项目组成员忙得焦头烂额,更不想找另外一个人来找自己的碴,而且其他项目组成员也很忙不太好意思请别人出来。
基于以上客观和心理状态,所以一个项目基本上就是开发测试交替进行,然后到项目完全开发完后,安排一个FTR。也就是下面这张图:

从上面这个图可以清晰地发现,Code Review放在最后。之前的Testing主要是QA做的黑盒测试,而有些Bug在不看代码做白盒的情况下很难测出来,现实是QA很少有做白盒看代码的能力,于是所有“别人看代码”的工作被放在了项目的后期。这样带来的结果是:
1. 一些小的Coding style和比较容易改的Bug被改掉;
2. 一些需要改动多处,改动Common function的Bug因为时间关系被Pending。因为QA之前完成了测试,如果再次改动关键被引用点,那么QA需要从头到尾彻底地重新测试一遍才能确保改动有效且不会引入Regression bug(即因为改动其他Bug而引入的新Bug),而deadline已经不允许这么干了。
可以容易发现,第二种Bug的改动价值更大,能够更大的提升软件质量,但是因为时间带来的风险原因而不得不“明知道是Bug,但是不改了”。
针对这个问题,我们来看看基本上被弃用的原始版瀑布开发模型(讲解使用,切勿模仿):
Testing在最后才引用进来,中间没有迭代Testing。DEV一条道开发到黑,全部开发完成后,然后QA开始测试。现在看起来都比较可笑,因为Bug是越早发现越好,越晚发现,修复bug的effort(成本)会成倍增加。Testing如此,为何Code Review不如此?

现在的解决方案是:
1. 增加Code Review Sprint。在项目的编码和测试阶段,会有3-4个左右的迭代deliverable,那么在每次deliverable之前,必须组织一次Code Review。具体的时间可以根据各个项目组的繁忙程度灵活调节。
2. 将Code Review Sprint写入流程,并且准备好合适的文档Excel表格用来提交Bug和对Code Reviewer的效果统计,确保执行力。
3. 每次Code Review Sprint大概持续时间是半小时到一小时。
4. Code Review Sprint发现的Bug种类有Coding Style, 算法逻辑,代码的严谨性,甚至Business Logic。
5. 在每次需求分析阶段可以适当引入不太忙的其他项目组成员,他们不用知道太多业务逻辑,只要知道大概业务逻辑和软件大功能点,以便日后做Review。(在软件行业的人混长了都有感觉,看界面就能大概猜到基本的UI逻辑)
Test Case Review Sprint亦如此,找其他项目组的QA来Review 本项目组的Test case,确保Test case格式正确,功能的覆盖面,正反测试用例的比例。
这样一来,很多关键Bug或者影响性能的瓶颈Risk能够在早期就被发现并被扼杀在摇篮之中,改动的Effort很小并防止了对以后代码的进一步影响。当然由于时间和资源有限的关系,这种Code Review可能不彻底,所以最后仍然加上一个FTR,做一次全项目组的技术评审。(题外话:其实很多人不太重视Code Review, 公司SQA在统计中发现Code Review中发现的Bug价值比黑盒测试中高10倍以上)
最近的一次项目尝试使用上面的方案,客户在电话里面说非常满意软件质量。
于是,就出现下面一个场景:
一位穿白大褂的医生表情轻松地走入了病房,对一个躺在病床上的小伙子说:CT显示你的大脑里面有一颗良性的肿瘤,现在用手术可以轻松解决。但是如果现在不做手术,你70岁的时候可能要在ICU(重症监护室)里面度过了。
小伙子:谢谢医生,现在可以手术吗?
医生:嗯,马上!
与此同时。。。
一位穿衬衫的高级软件工程师表情轻松地走入办公室,对一个正在埋头写代码的工程师说:刚才我花了半个小时做了个Code Review Sprint,发现你的代码里面有一处性能瓶颈风险。现在如果不改的话,那么将对以后的代码造成严重的影响,最后到客户那边的大数据负载下会不堪重负。
工程师:谢谢,您辛苦了,现在我可以将改动Commit进去吗?
高级工程师:嗯,马上!