在软件项目开发中,我们经常提到一个词“code review”。code review中文翻译过来就是代码评审或复查,简而言之就是编码完成后由其他人通过阅读代码来检查代码的质量(可编译、可运行、可读、可维护、可复用),这些性质都比较抽象,但是一般都可以通过以下的检查点来实现:
- 检查代码的命名方式是否符合规范,代码的可读和可维护必须要求所有参与编码的同事使用的命名有统一的规范(注意每个人有自己的代码风格,但是要符合可读性的代码规范);
- 检查代码的注释,我认为注释至少包括:1.类要有类用途和使用事项说明;2.方法要有用途和参数、返回值说明;3.重要语句说明;
- 检查代码的实现方式合适,包括逻辑判断、循环、错误处理、线程、性能等是否符合可拓展和可复用的要求;
- 检查代码结构的问题,检查方法和类是否做到松耦合,方法、类等逻辑块的代码量是否合适、是否有重复编码等等;
- 检查代码的可测试性,检查对重要的功能方法是否有测试案例,测试案例的覆盖性和针对性是否足够。
- 其他根据所在团队或组织要求进行审查的内容。
需要注意的是,代码进入code review之前已经可以编译运行,参与code review的人不负责代码的正确性,这应该是码农和QA负责的工作,也应该通过单元测试等方法来验证。如果按照上述的方式进行code review的话,在python脚本设计中进行code review应该注意python的常见命名方式、注释和编码规范。
我认为CodeReview最重要的是公司支持存在这样的机制以及程序员有这样的习惯。这一点如何实行还有待进一步的探索。
Python的编码规范
我会在另外一篇博文《python的统一编码规范》中进行详细讲述。
以下两篇博文是我觉得理解code review比较深入的文章,可以好好看一下:
Code Review中的几个提示
原文链接:http://coolshell.cn/articles/1302.html
Code Review应该是软件工程最最有价值的一个活动,之前,本站发表过《简单实用的Code Review工具》,那些工具主要是用来帮助更有效地进行这个活动,这里的这篇文章,我们主要想和大家分享一下Code Review代码审查的一些心得。
首先,我们先来看看Code Reivew的用处:
- Code reviews 中,可以通过大家的建议增进代码的质量。
- Code reviews 是一个传递知识的手段,可以让其它并不熟悉代码的人知道作者的意图和想法,从而可以在以后轻松维护代码。
- Code reviews 也鼓励程序员们相互学习对方的长处和优点。
- Code reviews 也可以被用来确认自己的设计和实现是一个清楚和简单的。
你也许注意到了在上面的Code Reivew中的诸多用处中,我们没有提到可以帮助找到程序的bug和保证代码风格和编码标准。这是因为我们认为:
- Code reviews 不应该承担发现代码错误的职责。Code Review主要是审核代码的质量,如可读性,可维护性,以及程序的逻辑和对需求和设计的实现。代码中的bug和错误应该由单元测试,功能测试,性能测试,回归测试来保证的(其中主要是单元测试,因为那是最接近Bug,也是Bug没有扩散的地方)
-
Code reviews 不应该成为保证代码风格和编码标准的手段。编码风格和代码规范都属于死的东西,每个程序员在把自己的代码提交团队Review的时候,代码就应该是符合规范的,这是默认值,属于每个人自己的事情,不应该交由团队来完成,否则只会浪费大家本来就不够的时间。我个人认为“meeting”是奢侈的,因为那需要大家在同一时刻都挤出时间,所以应该用在最需要的地方。代码规范比起程序的逻辑和对需求设计的实现来说,太不值得让大家都来了。
10年前,上面这两件事会是理所当然的(10年前的中国的软件开发还没有Code Reivew呢),今天,在中国的很多公司上面这两件事依然被认为是Code Reivew最重要的事,所以,我能够看到很多开发Team抱怨Code Review就是一个形式,费时费力不说,发现的问题还不如测试,而评审者们除了在代码风格上有些见术,别的也就没什么用了,长而久之,大家都会开始厌烦这个事了。
所以,在今天,请不要把上面的那两件事分散了Code Review的注意力,取而代之的是,对于Bug,程序的作者要在Review前提交自己的单元测试报告(如:XUnit的测试结果),对于代码规范,这是程序作者自己需要保证的,而且,有一些工具是可以帮你来检查代码规范的。
当然,上述这些言论并不是说,你不能在Code Review中报告一个程序的bug或是一个代码规范的问题。我只是说,那并不是Code Review的意图。
下面是我们认为的几个小提示可以让你更好进行Code Review这项最有价值的活动。
1.- 经常进行Code Review
以前经历过几个相当痛苦的Code Review,那几次Code Review都是在程序完成的时候进行的,当你面对那近万行的代码,以前N多掺和在一起的功能,你会发现,整个Code Review变得非常地艰难,用不了一会儿,你就会发现大家都在拼命地打着哈欠,但还是要坚持,有时候,这样的Review会持续3个小时以上,相当的夸张。而且,会议上会出现相当多的问题和争论,因为,这就好像,人家都把整个房子盖好了,大家Review时这挑一点那挑一点,有时候触动地基或是承重墙体,需要大动手术,让人返工,这当然会让盖房的人一下就跳起来极力地维护自己的代码,最后还伤了团队成员的感情。
所以,千万不要等大厦都盖好了再去Reivew,而且当有了地基,有了框架,有了房顶,有了门窗,有了装修,的各个时候循序渐进地进行Review,这样反而会更有效率,也更有帮助。
下面是一些观点,千万要铭记:
- 要Review的代码越多,那么要重构,重写的代码就会越多。而越不被程序作者接受的建议也会越多,唾沫口水战也会越多。
- 程序员代码写得时候越长,程序员就会在代码中加入越来越多的个人的东西。 程序员最大的问题就是“自负”,无论什么时候,什么情况下,有太多的机会会让这种“自负”澎涨开来,并开始影响团队影响整个项目,以至于听不见别人的建议,从而让Code Review变成了口水战。
-
越接近软件发布的最终期限,代码也就不能改得太多。
我个人的习惯,并且也是对团队成员的要求是——先Review设计实现思路,然后Review设计模式,接着Review成形的骨干代码,最后Review完成的代码,如果程序复杂的话,需要拆成几个单元或模块分别Review。当然,最佳的practice是,每次Review的代码应该在1000行以内,时间不能超过一部电影的时间——1.5小时(因为据说那个一个正常人的膀胱可以容纳尿液的最长限度)
当然,在敏捷开发中,他们不需要Code Reivew,其实,敏捷开发中使用更为极端的“结对编程”(Pair-Programming)的方法 —— 一种时时刻刻都在进行Code Review的方法,个人感觉在实际过程中,这种方法有点过了。另外,大家可以看看本站的另一篇文章《结对编程的利与弊》来了解一下这种方法的问题。
2.- Code Review不要太正式,而且要短
忘了那个代码评审的Checklist吧,走到你的同事座位跟前,像请师父一样请他坐到你的电脑面前,然后,花5分钟给他讲讲你的代码,给他另外一个5分钟让他给你的代码提提意见,这比什么都好。而如果你用了一个Checklist,让这个事情表现得很正式的话,下面两件事中必有一件事会发生:
- 只有在Checklist上存在的东西才会被Review。
- Code Reviews 变成了一种礼节性的东西,你的同事会装做很关心你的代码,但其实他心里想着尽快地离开你。
只有不正式的Code Review才会让你和评审者放轻松,人只有放松了,才会表现得很真实,很真诚。记住Review只不过是一种形式,而只有在相互信任中通过相互的讨论得到了有意义和有建设性的建议和意见,那才是最实在的。不然,作者和评审者的关系就会变成小偷和警察的关系。
3.- 尽可能的让不同的人Reivew你的代码
这是一个好主意,如果可能的话,不要总是只找一个人来Review你的代码,不同的人有不同的思考方式,有不同的见解,所以,不同的人可以全面的从各个方面评论你的代码,有的从实现的角度,有的从需求的角度,有的从用户使用的角度,有的从算法的角度,有的从性能效率的角度,有的从易读的角度,有的从扩展性的角度……,啊,好多啊,还让不让人活了。不管怎么说,多找一些不同的人会对你很有好处。当然,不要太多了,人多嘴杂反而适得其反,基本上来说,不要超过3个人,这是因为,这是一个可以围在一起讨论的最大人员尺寸。
下面是几个优点:
- 从不同的方向评审代码总是好的。
- 会有更多的人帮你在日后维护你的代码。
- 这也是一个增加团队凝聚力的方法。
4.- 保持积极的正面的态度
再说一次,程序最大的问题就是“自负”,尤其当我们Reivew别人的代码的时候,我已经见过无数的场面,程序员在Code Review的时候,开始抨击别人的代码,质疑别人的能力。太可笑了,我分析了一下,这类的程序员其实并没有什么本事,因为他们指责对方的目的是想告诉大家自己有多么的牛,靠这种手段来表现自己的程序员,其实是就是传说中所说的“半瓶水”。
所以,无论是代码作者,还是评审者,都需要一种积极向上的正面的态度,作者需要能够虚心接受别人的建议,因为别人的建议是为了让你做得更好;评审者也需要以一种积极的正面的态度向作者提意见,因为那是和你在一个战壕里的战友。记住,你不是一段代码,你是一个人!
5.- 学会享受Code Reivew
这可能是最重要的一个提示了,如果你到了一个人人都喜欢Code Reivew的团阿,那么,你会进入到一个生机勃勃的地方,在那里,每个人都能写出质量非常好的代码,在那里,你不需要经理的管理,团队会自适应一切变化,他们相互学习,相互帮助,不仅仅是写出好的代码,而且团队和其中的每个人都会自动进化,最关键的是,这个是一个团队。
从Code Review 谈如何做技术
原文链接:http://blogread.cn/it/article/6842?f=wb
这两天,在微博上表达了一下Code Review的重要性。因为翻看了阿里内部的Review Board上的记录,从上面发现Code Review做得好的是一些比较偏技术的团队,而偏业务的技术团队基本上没有看到Code Review的记录。当然,这并不能说没有记录他们就没有做Code Review,于是,我就问了一下以前在业务团队做过的同事有没有Code Review,他告诉我不但没有Code Review,而且他认为Code Review没用,因为:
1)工期压得太紧,时间连coding都不够,以上线为目的,
2)需求老变,代码的生命周期太短。所以,写好的代码没有任何意义,烂就烂吧,反正与绩效无关。
我心里非常不认同这样的观点,我觉得我是程序员,我是工程师,就像医生一样,不是把病人医好就好了,还要对病人的长期健康负责。对于常见病,要很快地医好病人很简单,下猛药,大量使用抗生素,好得飞快。但大家都知道,这明显是“饮鸩止渴”、“竭泽而渔”的做法。医生需要有责任心和医德,我也觉得程序员工程师也要有相应的责任心和相应的修养。东西交给我我必需要负责,我觉得这种负责和修养不是”做出来“就了事了,而是要到“做漂亮”这个级别,这就是“山寨”和“工业”的差别。而只以“做出来”为目的标准,我只能以为,这样的做法只不过是“按部就班”的堆砌代码罢了,和劳动密集型的“装配生产线”和“砌砖头”没有什么差别,在这种环境里呆着还不如离开。
老实说,因为去年我在业务团队的时候,我的团队也没有做Code Review,原因是多样的。其中一个重要原因是,我刚来阿里,所以,需要做的是在适应阿里的文化,任何公司都有自己的风格和特点,任何公司的做法都有他的理由和成因,对于我这样的一个初来者,首要的是要适应和观察,不要对团队做太多的改动,跟从、理解和信任是融入的关键。(注:在建北京团队和不要专职的测试人员上我都受到了一些来自上面和下面的阻力),所以跟着团队走没有玩Code Review。干了一年后,觉得我妥协了很多我以前所坚持的东西,觉得自己的标准在降低,想一想后背拔凉拔凉的,所以我决定坚持,而且还要坚持高标准。
对于Code Review很重要的这个观点,在微博上抛出来后,被一些阿里的工程师,架构师/专家,甚至资深架构师批评,我在和他们回复和讨论的过程中,居然发现有个把“因为对方用户的设置”我无法回复了(我被拉黑了)。这些批评我的阿里工程师/架构师的观点总结一下如下:(还有一些直接就是冷讽和骂人了,微博中我就直接删除了)(顺便说一下,阿里内还是有很多团队坚持做Code Review的)
1)到业务团队体会一下,倒逼工期的项目有多少?订好交付日期后再要求提前1个月的有多少?现在是做到已经不容易,更不谈做得漂亮!。
2)Code Review是一种教条,意义不大,有测试,只要不出错,就可以了。
3)目标都是改进质量,有限的投入总希望能有最大的产出,不同沉湎改进质量的方式不一样,业务应用开发忙的跟狗一样,而且业务逻辑变化快,通用性差,codereviw的成本要比底层高。
4)现在的主要矛盾是倒排出来的工期和不靠谱的程序员之间的矛盾,我认为cr不是解决这个问题的银弹。不从实际情况出发光打正义的嘴炮实在太过于自慰了 。
我们可以看到,上面观点其实和Code Review没有太多关系,其实是在抱怨另外的问题。这些观点其实是技术团队和业务团队的矛盾,但不知道为什么强加给了我的“Code Review很重要”的这个观点,然后这些观点反过来冲击“Code Reivew”,并说“Code Review无用”。这种讨论问题的方式在很常见,你说A,我说B,本来A、B是两件事,但就是要混为一谈,然后似是而非的用B来证明你的A观点是错的。(也许,这些工程师/架构师心存怨气,需要一个发泄的通道)
我觉得,很多时候,人思考问题思考不清楚,很大一部分原因是因为把很多问题混为一谈,连我自己有些时候都会这样。引以为戒。
即然被混为一谈,那我就来拆分一下,也是下面这三个问题:
Code Review有没有用的问题。
Code Review做不起来的问题。
-
业务变化快,速度快的问题,技术疲于跟命。
Code Review
你Google一下Code Reivew这个关键词,你就会发现Code Review的好处基本上是不存在争议的,有很多很多的文章和博文都在说Code Review的重要性,怎么做会更好,而且很多公司在面试过程中会加入“Code Review”的问题。打开Wikipedia的词条你会看到这样的描述——
卡珀斯·琼斯(Capers Jones)分析了超过12,000个软件开发项目,其中使用正式代码审查的项目,发现潜在缺陷率约在60-65%之间,若是非正式的代码审查,发现潜在缺陷率不到50%。大部份的测试,发现的潜在缺陷率会在30%左右。
一般的代码审查速度约是一小时150行程序码,对于一些关键的软件(例如安全关键系统的嵌入式软件),一小时审查数百行程序码的审查速度太快,可能无法找到程序中的问题。代码审查一般可以找到及移除约65%的错误,最高可以到85%。
也有研究针对代码审查找到的缺陷类型进行分析。代码审查找到的缺陷中,有75%是和计算机安全隐患有关。对于产品生命周期很长的软件公司而言,代码审查是很有效的工具。
Code Review的好处我觉得不用多说了,主要是让你的代码可以更好的组织起来,有更易读,有更高的维护性,同时可以达到知识共享,找到bug只是其中的副产品。这个东西已经不新鲜了,你上网可以找到很多文章,我就不多说了。就像你写程序要判断错误一样,Code Review也是最基本的常识性的东西。
我从2002年开始就浸泡在严格的Code Review中,我的个人成长和Code Review有很大的关系,如果我的成长过程中没有经历过Code Review这个事,我完全不敢想像。
我个人认为代码有这几种级别:1)可编译,2)可运行,3)可测试,4)可读,5)可维护,6)可重用。通过自动化测试的代码只能达到第3)级,而通过Code Review的代码少会在第4)级甚至更高。关于Code Review,你可以参看本站的《Code Review中的几个提示》
可见,Code Review直接关系到了你的工程能力!
Code Review 的问题
有下面几个情况会让你的Code Review没有效果。
首当其冲的是——“人员能力不足”,我经历过这样的情况,Code Review的过程中,大家大眼瞪小眼,没有什么好的想法,不知道什么是好的代码,什么是不好的代码。导致Code Review大多数都在代码风格上。今天,我告诉你,代码风格这种事,是每个程序员自查的事情,不应该浪费大家的时间。对此,我有两个建议:1)你团队的人招错了,该换血了。2)让你团队的人花时候阅读一下《代码大全》这本书(当然,还要读很多基础知识的书)。
次当其冲的是——“结果更重要”,也就是说,做出来更重要,做漂亮不重要。因为我的KPI和年终奖based on how many works I’ve done!而不是How perfect they are ! 这让我想到那些天天在用Spring MVC 做CRUD网页的工程师,我承认,他们很熟练。大量的重复劳动。其实,仔细想一下好多东西是可以框架化,模板化,或是自动生成的。所以,为了堆出这么多网页就停地去堆,做的东西是很多,但是没有任何成长。急功近利,也许,你做得多,拿到了不错的年终奖,但是你失去的也多,失去了成为一个卓越工程师的机会。你本来可以让你的月薪在1-2年后翻1-2倍的,但一年后你只拿到了为数不多的年终奖。
然后是——“人员的态度问题”,一方面就是懒,不想精益求精,只要干完活交差了事。对此,你更要大力开展Code Review了,让这种人写出来的代码曝光在更多人面前,让他为质量不好的代码蒙羞。另一方面,有人会觉得那是别人的模块,我不懂,也没时间 去懂,不懂他的业务怎么做Code Review? 我只想说,如果你的团队里这样的“各个自扫门前雪”的事越多,那么这个团队也就越没主动性,没有主动性也就越不可能是个好团队,做的东西也不可能好。而对于个人来说,也就越不可能有成长。
接下来是——“需求变化的问题”,有人认识,需求变得快,代码的生存周期比较短,不需要好的代码,反正过两天这些代码就会被废弃了。如果是一次性的东西,的确质量不需要太高,反正用了就扔。但是,我觉得多多少少要Review一下这个一次性的烂代码不会影响那些长期在用的代码吧,如果你的项目全部都是临时代码,那么你团队是不是也是一个临时团队?关于如果应对需求变化,你可以看看本站的《需求变化与IoC》《Unix的设计思想来应对多变的需求》的文章 ,从这些文章中,我相信你可以看到对于需求变化的代码质量需要的更高。
最后是——“时间不够问题”,如果是业务逼得紧,让你疲于奔命,那么这不是Code Review好不好问题,这是需求管理和项目管理的问题以及别的非技术的问题。下面我会说。
不管怎么样,上述Code Review的问题不应该成为“Code Review无意义”的理由或借口,这就好像“因噎废食”一样。干什么事都会有困难和问题的,有的人就这样退缩了,但有的人看得到利大于弊,还是去坚持,人与人的不同正在这个地方。这就是为什么运动会受伤,但还是会人去运动,而有人因为怕受伤就退缩了一样。
被业务逼得太紧
被业务逼得太紧,需求乱变,这其实和Code Review没有多大关系了。对此,我想先讲一个我的故事。
我去年在阿里的聚石塔,刚去的时候,聚石塔正在做一个很大的重构——对架构的大调整。因此压了很多业务需求,等这个项目花了2-3个月做完了后,一下子涌入了很多30-50个需求,搞得团队疲于奔命。在累了两周后,我仔细分析了一下这些需求,发现很多需求是在重复做阿里云已经做过的东西,还有一些需求是因为聚石塔这个平台不规范没有标准所产生的问题。于是,我做了这么三件事:
1)重新定义聚石塔这个产品主要目标和范围,确定哪些该做,哪些不该做。
2)为聚石塔制定标准 ,让阿里云的API都长得基本一样,并制订云资源的接入标准。
3)推动重构阿里云的Portal系统,不再实现队里云已经做过的东西,与阿里云紧密结合。
这些事情推动起来并不容易,聚石塔的业务方一开始也不理解,我和产品一起做业务方的工作,而阿里云也被我逼得很惨(在这里一并感谢,尤其阿里云的同学,老实说,和阿里云跨团队合作中是我这么多年来感觉最好的一次,相当赞)。通过这个事,聚石塔需求一下就有质的下降了。搞得还有几个工程师来和我说,你这么搞,聚石塔就没事可干了。姑且不说工程师对聚石塔的理解是怎么样的。 我只想说,我大量地减少了需求,尽最大可能联合了该联合的人,而不是自己闭门造车,并让产品的目标和方向更明确了。做了这些事情后,大家不但不用加班,而且还有时间充电去学技术,并为聚石塔思考未来的方向和发展。去年公司996的时候,我的团队还在965(搞得跟异教徒似的),而且还有很多时间去专研新的东西。
说这个故事,我不是为了得瑟,而是因为有些人在微博上抨击我是一个道貌岸然的只会谈概念讲道理的装逼犯。所以,我告诉大家我在聚石塔是怎么做的,我公开写在这里,你也可以向相关的同学去求证我说的是不是真的。也向你证明,我可能是个装逼犯,但绝不是只会谈概念讲道的装逼犯。
被业务方逼得紧不要抱怨,你没有时间被逼得像牲口一样工作,这个时候,你需要的是暂停一下想一想,为什么会像牲口一样?而这正是让你变得聪明的机会。
我为你总结一下,
1)你有没有去Review业务部门给你的这么多的需求,哪些是合理的,哪些是不合理的。在Amazon,开发工程师都会被教育拿到需求后一定要问——“为什么要做?业务影响度有多大?有多少用户受益?”,回答不清这个问题,没有数据的支持,就不做。所以,产品经理要做很多数据挖拙和用户调研的工作,而不是拍拍脑袋,听极少数的用户抱怨就要开需求了。
2)产品经理也要管理和教育的。你要告诉你的产品经理:“你是一个好的产品经理,因为你不但对用户把握得很好,也会对软件工艺把握得很好。你不但会开出外在的功能性需求,也同样会开出内在的让软件系统更完善的非功能性需求。你不是在迁就用户,而是引导用户。你不会无限制地加功能,而是把握产品灵魂控制并简化功能。你会为自己要做的和不做东西的感到同样的自豪。”你要告诉你的产品经理:“做一个半成品不如做好半年产品”(更多这样的观点请参看《Rework摘录和感想》)
3)做事情是要讲效率的。Amazon里喜欢使用一种叫T-Shirt Size Estimation的评估方法来优先做投入小产出大的“Happy Case”。关于什么是效率,什么是T-Shirt Size Estimation,你可以看看《加班与效率》一文 。
4)需求总是会变化的,不要抱怨需求变化太快。你应该抱怨的是为什么我们没有把握好方向?老变?这个事就像踢足球一样,你要去的地方是球将要去的地方,而不是球现在的地方。你要知道球要去哪里,你就知道球之前是怎么动的,找到了运动轨迹后,你才知道球要去像何方。如果你都不知道球要去向何方,那你就是一只无头苍蝇一样,东一下西一下。
当你忙得跟牲口一样,你应该停下来,问一下自己,自己成为牲口的原因,是不是就是因为自己做事时候像就牲口一样思考?
其它
最后,我在给阿里今年新入职的毕业生的“技塑人生”的分享中,我给他们布置了5、6Homework,分享几个给大家:
1)重构或写一个模块,把他做成真正的Elegent。
2)与大家分享一篇或几篇技术文章 ,并收获10-30个赞。
3)降低现有至少20%的重复工作或维护工作
4)拒绝或简化一个需求(需要项目中所有的Stakeholders都同意)
部署这些作业的原因,是我希望新入行的同学们对自己的工作坚持高的标准,我知道你们会因为骨感的现实而妥协,但是我希望你们就算在现实中妥协了也要在内心中坚持尽可能高的标准,不要习惯成自然,最后被社会这个大染缸给潜移默化了。因为你至少要对自己负责。
芝兰生于空谷,不以无人而不芳!君子修身养道,不以穷困而改志!