代码Review

 在软件开发的项目中, Code Review是保证代码质量非常重要的一个环节,其主要工作是:
1、发现代码中的bug;
2、从代码的易维护性、可扩展性角度考察代码的质量,提出修改建议。

1、代码中的bug必定出现在编码常识和商业逻辑相关的地方:
(1) 编码常识方面的bug: 比如,系统中打开的流/文件/连接等没有及时关闭;或是存在thread safe问题,或是存在性能低下问题等,这类问题对有经验的开发人员是比较容易发现的。在Review之前一定要消灭各种类似拼写、低级的转换等的错误。

(2)、与商业逻辑相关的bug。   这类bug是非常隐蔽的,如果有对产品不熟悉的人参与该产品的项目开发,容易出现这类的bug。为了避免这类bug的出现,除了在Use Case和Test Case中详细描述以正确指导开发人员并在测试时能及时发现它之外,Code Review也是不可缺少的保证环节。在代码review之前需要参与者充分了解被Review内容,并且要对被Review的代码进行阅读,并且对不理解的地方作出笔记。
3 、代码Code Review的步骤 (1)、代码编写者和代码审核者坐在一起,由代码编写者按照Use Case/功能依次讲解自己负责的代码和相关逻辑,从表示层→逻辑层→数据读取层→DB层;
(2)、代码审核者在此过程中可以随时提出自己的疑问,由代码编写者进行解答。
(3)、代码讲解完毕后,参与人员将事先总结的不理解的地方提出,由代码编写者给与解答。

(4)、代码审核者根据审核的结果编写“代码审核报告”,“审核报告”中记录发现的问题及修改建议,然后把“审核报告”发送给相关人员。

(5)、代码编写者根据“代码审核报告”给出的修改意见,修改好代码,有不清楚的地方可积极向代码审核者提出。

(6)、代码编写者 bug fix完毕之后给出反馈。

(7)、代码审核者把Code Review中发现的有价值的问题更新到"代码审核规范"的文档中,对于特别值得提醒的问题可群发email给所有技术人员。

关于Java方面的日本外包应该关注的地方:

1 java编码规范方面检查项

检查项参照java编码规范执行,见《java编码规范(java code conventions)》

2 面向对象设计方面检查项

主要包含以下方面
a)       类设计和抽象是否合适
b)       是否符合面向接口编程的思想
c)       是否采用合适的设计范式

3 性能方面检查项

性能检查在大多数代码中都是需要严重关注的方面,也是最容易出现问题的方面,常常有程序员写出了功能和语法没有丝毫问题的代码后,正式运行时却在性能上表现不佳,从而不得不做大量的返工,甚至是推倒重来。
a)       在海量数据出现时,队列,表,文件,在传输,upload等方面是否会出现问题,有无控制,如分配的内存块大小,队列长度等控制参数
b)       对hashtable,vector等集合类数据结构的选择和设置是否合适,如正确设置capacity,load factor等参数,数据结构的是否是同步的
c)       有无滥用string对象的现象
d)       是否采用通用的线程池、对象池模块等cache技术以提高性能
e)       类的接口是否定义良好,如参数类型等,避免内部转换
f)       是否采用内存或硬盘缓冲机制以提高效率
g)       并发访问时的应对策略
h)       i/o方面是否使用了合适的类或采用良好的方法以提高性能(如减少序列化,使用buffer类封装流等)
i)         同步方法的使用是否得当,是否过度使用
j)         递归方法中的叠代次数是否合适,应该保证在合理的栈空间范围内
k)       如果调用了阻塞方法,是否考虑了保证性能的措施
l)        避免过度优化,对性能要求高的代码是否使用profile工具,如jprobe等

4 资源泄漏处理方面检查项

  对于java来说由于存在垃圾收集机制,所以内存泄漏不是太明显,但使用不当,仍然存在内存泄漏的问题。而对于其它的语言,如c++等在这方面就要严重关注了。当然数据库连接资源不释放的问题也是广大程序员最常见的,相信有很多的pm被这个问题折磨的死去活来。
a)       分配的内存是否释放,尤其在错误处理路径上(对非java类)
b)        错误发生时是否所有的对象被释放,如数据库连接、socket、文件等
c)       是否同一个对象被释放多次(对非java类)
d)       代码是否保存准确的对象reference计数(对非java类)

5 线程安全方面检查项

线程安全问题实际涉及两个方面,一个是性能,另一个是资源的一致性,我们需要在这两方面做个权衡,现在就是到了权衡利弊的时候了。
a)       代码中所有的全局变量是否是线程安全的
b)        需要被多个线程访问的对象是否线程安全,检查有无通过同步方法保护
c)       同步对象上的锁是否按相同的顺序获得和释放以避免死锁,注意错误处理代码
d)       是否存在可能的死锁或是竞争,当用到多个锁时,避免出现类似情况:线程a获得锁1,然后锁2,线程b获得锁2,然后锁1
e)        在保证线程安全的同时,要注意避免过度使用同步,导致性能降低

6 程序流程方面检查项

a)       循环结束条件是否准确
b)        是否避免了死循环的产生
c)       对循环的处理是否合适,如循环变量,局部对象,循环次数等能够考虑到性能方面的影响

7 数据库处理方面

很多code review人员在面对代码中涉及到的数据库可移植性和提高数据库性能方面的冲突时表现的无所适从,凡事很难两全其美的啊。
a)       数据库设计或sql语句是否便于移植(注意和性能方面会存在冲突)
b)       数据库资源是否正常关闭和释放
c)       数据库访问模块是否正确封装,便于管理和提高性能
d)       是否采用合适的事务隔离级别
e)       是否采用存储过程以提高性能
f)        是否采用preparedstatement以提高性能

8 通讯方面检查项

a)       socket通讯是否存在长期阻塞问题
b)       发送接收的数据流是否采用缓冲机制
c)       socket超时处理,异常处理
d)       数据传输的流量控制问题

9 java对象处理方面检查项

这个检查项的基础是对java对象有较深的理解,但现实是很多看过《thinking in java》的程序员,仍然在程序中无法区分传值和传引用,以及对象和reference的区别。这或许就是理论和实践难以结合的问题啊。正所谓知而不行,非真知也。
a)       对象生命周期的处理,是否对象的reference已经失效,能够设置为null,并被回收
b)       在对象的传值和传参方面有无问题,对象的clone方法使用是否过度
c)       是否大量经常的创建临时对象
d)       是否尽量使用局部对象(堆栈对象)
e)        在只需要对象reference的地方是否创建了新的对象实例

10 异常处理方面检查项

java中提供了方便的异常处理机制,但普遍存在的是异常被捕获,但并没有得到处理。我们可以打开一段代码,最常见的现象是进入某个方法后,一个大的try/catch将所有代码行括住,然后在catch中将异常打印到控制台,而且该异常是exception对象。
a)       每次当方法返回时是否正确处理了异常,如最简单的处理,记录日志到日志文件中
b)        是否对数据的值和范围是否合法进行校验,包括采用断言(assertion)
c)       在出错路径上是否所有的资源和内存都已经释放
d)       所有抛出的异常都得到正确的处理,特别是对子方法抛出的异常,在整个调用栈中必须能够被捕捉并处理
e)        当调用导致错误发生时,方法的调用者应该得到一个通知
f)        不要忘了对错误处理部分的代码进行测试,很多代码在正常情况下执行良好,而一旦出错,整个系统就崩溃了

11 方法(函数)方面检查项

a)       方法的参数是否都做了校验
b)        数组类结构是否做了边界校验
c)       变量在使用前是否做了初始化
d)       返回堆对象的reference,不要返回栈对象的reference
e)        方法api是否被良好定义,即是否尽量面向接口编程,便于维护和重构

12 安全方面检查项

a)       对命令行执行的代码,需要详细检查命令行参数
b)        web类程序检查是否对访问参数进行合法性验证
c)       重要信息的保存是否选用合适的加密算法
d)       通讯时考虑是否选用安全的通讯方式

13 其他

a)      日志是否正常输出和控制
b)        配置信息如何获得,是否有硬编码

猜你喜欢

转载自k1121.iteye.com/blog/1746700