代码REVIEW的工作是软件工程中不能忽视的工作,是软件质量活动之一,对保障和改善软件工程质量有比较明显的作用,特别是对团队进行开发的软件工程。本文主要以C代码的视角描述CODE REVIEW的一般方法。
一、代码REVIEW前的准备工作
了解软件的基本架构,软件层次关系以及模块间关系,业务流程的任务划分。这个要求是对设计文档需要比较详细的了解。如果没有详细的设计文档,至少要有比较清楚的业务流程和模块划分。
二、代码REVIEW的一般性检查
1、代码文件和目录的REVIEW
检查软件目录是否安排合理,是否按一定的规则进行,有的是按照软件的层次进行目录的分配,有的是按照功能模块进行目录的分配。比较糟糕的目录结构是按照部门和小组进行分配,对于整个软件系统来讲没有机构的概念,支持层次和模块的概念。检查文件命名是否符合编程规范,让人一看就知道此文件或目录说明了什么。
2、代码头文件的检查
容易犯的错误是代码头文件中,不区分内部使用还是外部使用头文件的包含关系是否按层次
3、函数名称的检查
文件中内部使用函数和外部使用函数,内部使用的函数不应暴露在对外使用的头文件中,内部使用函数名称是否和对外函数名称容易区别,函数命名是否符合编程规范,函数命名中使用的参数检查,是否函数中有太多的参数,是否可以使用结构来进行命名和描述
4、结构和变量
内部使用的结构和对外暴露的结构也要分辨清楚,头文件中只声明对外使用的结构,内部变量和外部变量分清楚,外部变量尽量少用,可以通过函数的方式进行获得。
5、函数体内的变量
是否定义太多的变量,很多时候,在调试中加入测试代码和变量,正式版本没有将多余的部分删除掉,在编译过程中一般都会有警告,可以关注变量没有使用的警告。
6、函数输入参数合法性
函数体内定义外变量,通常就是函数输入参数的检查,特别是空指针的检查,参数值的范围检查,这些都是代码可靠性的必须要进行的工作。
7、变量的初始化
在函数体内部使用的变量,通常都需要进行初始化,给变量一个缺省值,编译器不一定会给变量一个缺省值,定义的指针要赋值空间。
8、检查空间越界
数组下标的越界,指针空间的越界,需要重点关注,memcpy, memset, strcpy等的C函数也需要重点关注,常常犯错误。
9、循环执行体检查
FOR, WHILE, DO WHILE 循环的退出条件和中止条件的检查,常常是条件不对,数值多一个或少一个就退出或中止,特别是N,N+1, N-1到底是哪个值,还有是大于还是大于等于,小于还是小于等于。对于复杂的退出或中止条件一定要仔细检查,与或条件的检查,括号以及优先级检查。
10、条件执行体检查
IF ELSE 和SWITCH的检查,IF ELSE条件的充分完整性检查,SWITCH 多路选择的完整性检查,经常会出现遗漏的情况,IF 条件中“==”误写成“=”,眼神不好容易遗漏,同时编译警告有时也会不注意。
11、函数返回前检查
MALLOC临时申请的空间,是否释放FREE,在函数中途异常退出的地方,没有FREE,大家都习惯在函数最后进行释放,这个常常遗漏。返回值是否在设计范围内,返回的空间指针是否被收回。
三、代码REVIEW高层次检查
1、函数的多任务调用
全局变量的保护,加锁解锁,有的是函数下又封装了函数,这个问题就比较容易隐藏起来,定位比较困难。另外一个解决办法改多任务调用为单任务调用,从调用的架构上来修改。
2、临时内存数据传递的保护
在多任务系统中,有的任务将数据写到一空间以便另外的任务来读取,另外的任务在读的过程中,任务改写此空间内容,极端的就释放此空间。这种情况表现形式多样,不同的业务场景代码实现不同,比如读写通道,关闭通道,消息传递等等。
3、多任务下状态机迁移混乱
这个就属于设计不足,要么是设计中有遗漏的情况,要么就是设计状态机过于复杂,迁移条件太多。
4、下层模块的代码调用上层代码
这种情况不是不允许,而是不好,容易导致调用关系混乱,特别是多任务系统中,容易导致多任务调用。比较好的凡是是下层代码发消息给上层代码。
5、单个资源被多个任务使用
常用的解决方式是使用一个单独的调度任务进行此资源的使用,多个任务向这个任务请求使用,保证单个资源由一个任务来控制。
6、多任务的互锁
这个在多任务的程序中也不经意的会犯,好的解决方式是减少锁的设计,甚至是无锁设计,通过将资源进行管理的方式来降低多任务下的调用。
7、非阻塞和阻塞的使用
在多任务系统下,合理使用阻塞和非阻塞的函数实现,这个应该是设计时加以注意。明确那些任务是非阻塞运行,那些任务是可以阻塞运行。
8、业务流程中异常的处理
在复杂的业务流程中,正常的流程一般设计和编写代码都可以完成的很好,但是业务流程中都会有异常出现,设计中和编写代码中,如何尽可能将异常都考虑全面,处理的全面,是比较考功底的,异常的REVIEW也是关键,牵扯到业务流程的覆盖程度。
9、代码的扩展性进行REVIEW
业务经常是变化的,所以接口代码就要跟随修改,如何为后续修改带来方便,对接口设计和编写就要有一定的灵活性和可扩展性。可以参考链接https://blog.csdn.net/DQWKLC/article/details/91491972
10、代码复杂度的REVIEW
代码中的复杂度也是需要进行REVIEW的,特别是性能优化上,代码复杂,执行的效率一定会打折扣,而且容易出错。关键的算法应该通过设计减小复杂度,通过前期的伪码设计,减少或降低实际编写代码的难度。