一、代码复审Check List
1.概要部分
代码能符合需求和规格说明么?
符合要求,对于-c和-s的两种问题类型都能将结果输出到相应的sudoku.txt文件中,对于过程中所可能出现的错误也给出了错误信息。
代码设计是否有周全的考虑?
有周全的考虑。除了对于输入的处理比较完善之外,对于结果是否重复,结果是否正确也有内部的验证模块。
代码可读性如何?
可读性较好,在函数和变量的命名上都比较符合可读性的要求,比如generate_rand_sudoku, empty_value等多单词中间以“_”分隔,但是前期的一些版本注释比较少,在后面的提交中有所改进。
代码容易维护么?
一般,如果将sudoku的struct换成一个单独的类,并且增加相应的接口,可能对于以后的维护更有利。
代码的每一行都执行并检查过了吗?
单步执行并且检查过了。
2.设计模式部分
设计是否遵从已知的设计模式或项目中常用的模式?
基本上是按照问题解决思路来写,后续的过程是基本上是按照寻找问题,解决问题的思路,没有采用什么特定的模式。
有没有硬编码或字符串/数字等存在?
还是有一些的,比如下面的4,表示第一次左上角的数字应该是5,但第一遍阅读没有询问代码作者的情况下还是比较迷惑的。
empty_value[4][0][0] = true; // 1st row
empty_value[4][0][1] = true; // 1st col
empty_value[4][0][2] = true; // 1st block
代码有没有依赖于某一平台,是否会影响将来的移植(如Win32到Win64)?
没有明显的依赖,在windos系统下都是能跑的,无论是win32还是win64
开发者新写的代码能否用已有的Library/SDK/Framework中的功能实现?在本项目中是否存在类似的功能可以调用而不用全部重新实现?
开发者写了一个通过hash值比对的函数,在c++的库中有直接进行比较的函数,可以不用重复实现,其余的函数未发现可以通过调用直接实现的。
有没有无用的代码可以清除?(很多人想保留尽可能多的代码,因为以后可能会用上,这样导致程序文件中有很多注释掉的代码,这些代码都可以删除,因为源代码控制已经保存了原来的老代码。)
在一些中间版本(比如第4次提交的时候),还保留着生成单独一个数独的代码(void generate_rand_sudoku(short *data)),在后期直接批量生成的时候没有将这个函数删除,而是两者并存,可能会导致产生一些疑惑,但在最终版本中均将无用代码删除。
3.代码规范部分
修改的部分符合代码标准和风格么(详细条文略)?
总体上而言比较符合代码的相应标准,但在部分地方有一些无用的空行影响阅读体验。
4.具体代码部分
有没有对错误进行处理?对于调用的外部函数,是否检查了返回值或处理了异常?
对错误进行了处理(比如读入错误返回了错误信息),对于调用的外部函数也检查了返回值(比如fopen<=的情况做了检查)。
参数传递有无错误,字符串的长度是字节的长度还是字符(可能是单/双字节)的长度,是以0开始计数还是以1开始计数?
参数传递没有错误,长度是字节的长度,从0开始计数。
边界条件是如何处理的?Switch语句的Default是如何处理的?循环有没有可能出现死循环?
矩阵边界为0到81,部分三维矩阵为[9][9][3],没有switch语句,在第二和第三版中求解函数出现了死循环,但在后续最终版本中已经更正。
有没有使用断言(Assert)来保证我们认为不变的条件真的满足?
单元测试部分使用了Assert保证条件满足。
对资源的利用,是在哪里申请,在哪里释放的?有没有可能导致资源泄露(内存、文件、各种GUI资源、数据库访问的连接,等等)?有没有可能优化?数据结构中是否有无用的元素?
局部变量在初始化时申请,在函数结束时释放。
全局变量在初始化时申请,在整个程序结束的时候释放。
文件指针在文件打开的时候申请,在程序结束前释放。
未发现资源泄露的地方,可以将读入文件读完后立刻释放,没有必要最后一起释放。
数据结构中没有无用的元素。
5.效能
程序性能较好,生成的部分性能一般100w需要26s左右,而求解的部分性能较为优异。
代码中,特别是循环中是否有明显可优化的部分(C++中反复创建类,C#中string的操作是否能用StringBuilder 来优化)?
未发现可以做明显优化的部分。
对于系统和网络调用是否会超时?如何处理?
没有使用系统调用。
6.可读性
代码可读性如何?有没有足够的注释?
可读性总体比较好,在开始的几次提交(第二三四次)注释比较少,但是到最终版本注释能够很好地帮助程序的阅读。
7.可测试性
代码是否需要更新或创建新的单元测试?
经检查,代码的主要部分均已生成了相应的单元测试,没有明显需要新的测试的部分。
还可以有针对特定领域开发(如数据库、网页、多线程等)的核查表。
暂时未发现这种需求。
二、设计一个代码规范
工具提供的代码规范和你个人的代码风格有什么不同?
(1)应该用4个空格代替tab
(2){应该和代码在同一行,并且中间有一个空格
(3)else,else if应该与if的}在同一行,且中间应当有一个空格
(4)注释的“//”和代码不能直接相连,中间应该有空格
(5)不能够使用namespace
(6)每行的末尾不应该有空格
(7)没有copyright
工具提供的代码规范里有哪些部分是你之前没有想到的?
(1)应该用4个空格代替tab
(2){应该和代码在同一行,并且中间有一个空格
(3)else,else if应该与if的}在同一行,且中间应当有一个空格
(4)注释的“//”和代码不能直接相连,中间应该有空格
(5)不能够使用namespace
(6)每行的末尾不应该有空格
(7)没有copyright
为什么要这样规范?这样的规范有意义吗?
这种规范可以很大程度上优化代码的可读性,在多人合作开发的过程中可以提高效率,有助于接口的串联过程以及后期的测试和维护。
最后,请根据构建之法书上编码规范里提到的那些要点整理一份你们在结对编程时使用的代码规范。
(1)应该用4个空格代替tab
(2){应该和代码在同一行,并且中间有一个空格
(3)else,else if应该与if的}在同一行,且中间应当有一个空格
(4)注释的“//”和代码不能直接相连,中间应该有空格
(5)不能够使用namespace
(6)每行的末尾不应该有空格
(7)应该有copyright
(8)代码的中间不应该有无关注释和无用空行
(9)函数结束后应该与下个函数间空一行
(10)过多的函数声明可以放到单独的.h头文件中
(11)变量名如果由多个单词组成,从第二个起第一个字母应当大写
(12)避免无用函数依旧在代码中出现。
(13)不要使用goto语句
(14)不要将多行代码放在同一行(比如多个变量声明)
(15)变量的声明一定要有初始值