Code Inspection的checklist可以分两方面内容:基本编程原则检查和语言相关检查。
基本编程原则
基本编程原则对大多数语言都适用,尤其是面向对象语言。
- 格式
- 由于有IDE(Eclipse, Netbeans……)的支持,代码格式可以很容易地自动编排,统一大家的代码格式很方便。
- 乱糟糟的代码看起来很晕,没法让大家集中精力检查。
- 命名
- “编程语言”也是“语言”,需要传递信息。编程语言的规则能保证计算机能理解,但不能保证人能很好地理解。为了让人能理解,必须在变量、方法、类等命名方面下功夫,让人见名知意。
- 有一些基本的规则,如:类用名词、方法用动词、变量用名词等,可以参考各语言约定俗成的编程规范。
- 好的命名可以极大增加程序可读性。文档、注释也是为了理解程序。相较而言,程序同时还是最终真正“产品”,因此,应当让程序自身可读性加强,减少对文档和注释量的需求。这样在维护代码时会减少对文档和注释的维护量。
- 消灭魔数
- 所谓“魔数”指的是程序逻辑中包含的数字,这些数字可能在多处出现,或可能随时调整,如:
- if(user.type==1) ......
- 1代表嘛意思?得写个注释。如果定义成常量,有个名字,这地方就好理解多了。同时修改常量值比在代码中到处替换容易多了。
- 注释
- 意义就不用说了,老生常谈了。
- 虽然老生常谈,但往往做成了两个极端:太少,太多。
- 太少不奇怪,毕竟没有注释编译时也不会报错,人本性总有惰性。
- 太多怎么可能呢,多了怕嘛?!的确有太多的情况出现,恨不得每一句话都写一个注释,解释这句话的作用,或者在每个方法、程序块前详细描述其中的操作过程,代码就是注释的映射。这就太过了:首先,打开程序看的应该都是程序员,看合格的代码应该不会比看大段的注释难,注释白费了。其次,稍微修改程序就得同步修改注释,否则以后以谁为准?麻烦得很!
- 注释解释这段代码解决什么问题;代码本身接受如何解决。
- 解决两地分居
- 变量声明和使用相隔太远,或超过了必要的生命范围。
- 在某些语言中,这是语言自身的限制,只得将就了。但对于变量声明位置灵活的语言,再这样做就不厚道了。
- 变量就近声明;最小化生命范围。
- 重复代码
- 计算机上copy & paste太方便了,以至于大段的代码在程序中不断copy & paste。
- 由于copy & paste的太快,往往该改的地方没有改过来,产生bug。
- 修改代码的时候,由于被paste到太多地方,往往修改不完全,产生bug。
- 应该训练一种意识,写代码时只要按ctrl+C的时候就好好想想能否把copy的东西抽出来做成共用方法,避免重复代码。
- 即使没有copy & paste,多次手写重复代码也应有以上意识。
- 长方法
- 长方法难于阅读,受限于人脑的“缓存”,往往读了后面忘了前面,尤其在上下翻屏的情况下。
- 抽出多个方法。主逻辑中通过方法名就可以知道逻辑过程,岂不美哉?!
- 抽出的方法别其他地方调用的可能性大大增加,减少重复代码。
- 巨类
- 无所不包的类。由于包含了太多的功能,没有一个明确的现实对应,“四不象”。命名困难就是一个信号。
- 一个类只应该有一个方面功能,不要多管闲事。
- 耦合度
- 类/模块之间的耦合度应尽量低。来回频繁反复调用应该避免。
- 往往由于类/模块之间功能划分不合理造成。把方法放到合适的类/模块中去。
- 调用者在一个逻辑中多次调用被调用者的方法。可以认为是“微观管理”。
- Don't ask for the information you need to do the work; ask the object that has the information to do the work for you.
- 滥用全局/成员变量
- 全局变量是否是必须的?
- 成员变量是否应该是类的一个属性?
- ……
语言相关检查
各语言有自己的pitfalls需要检查。例如Java中:
- null
- 是否在使用对象变量前判断不等于null?
- equals
- 对象的比较应该用equals。除非比较两个对象是否为“同一”对象,否则不能用==比较。
- 自定义类,如果需要用equals比较,是否重写了equals方法?
- 资源释放
- 如IO操作使用的file、socket等资源,需要在使用后主动释放。
- 为了保证资源的释放,需要在finally中主动释放。
- ……