显示标签为“code inspection”的博文。显示所有博文
显示标签为“code inspection”的博文。显示所有博文

2007-06-30

Java/OOP Code Inspection Checklist

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中主动释放。
  • ……

2007-06-28

Effective review

如何在软件项目中进行effective review?这是个问题。

在时间紧张的时候,大家过于关注自己的部分,往往对其他人的工作没有足够的熟悉程度,这时候进行review往往得不到好的效果,尤其是在不提前进行准备的情况下。

一直以来,认为大家先在底下独自review,然后再聚到一起把review结果汇报一下的做法不经济,所以选择让大家会上当场review,随着owner的引导,大家一路review过去。但一直有一个问题:很多人跟不上队伍,或者干脆不打算跟上,这样的review会留下很多隐患,以至于有些功能遗漏居然没有发现。其实大家独自review也会有这个问题,只是时间宽松一点,可以做的细致一点而已,但同样没有效率。

review最根本的功能有两个方面:例行检查与功能检查。例行检查目标是找出不符合普遍规范的地方,例如文档不完整,code形式不符合规范等。功能检查的目标是找出错误理解需求或遗漏需求的地方,也包括算法或架构性能、安全等方面的缺陷。

在采用现场review的时候,由于节奏很快,把这两方面的检查一起进行,可能就会导致很多人“身在曹营心在汉”的状况,review草草收场。

怎么办?分开呗,进行至少两遍review,第一遍例行检查,第二遍功能检查。如果有意见,也可以颠倒顺序。例行检查根据checklist进行,功能检查根据上一环节的input,如需求文档,设计文档等。

Document Review

首先owner展示文档,reviewer检查各部分是否齐全,是否遵守约定的模板。第二遍功能检查视各文档目的而定,如设计文档要看能否覆盖需求,如果不能,是否已在文档中指出。

Code Inspection

1.功能检查

按scenario进行,owner需要在会前准备scenario,并且标注每个scenario对应的需求点。

Inspection的第一步是检查scenario是否符合需求,覆盖所有需求点。

接下来对着每个scenario进行功能实现检查。

2.例行检查

例行检查的checklist需要在项目启动的时候定义好,或在编码前定义好,如果有人不熟悉,需要进行培训或沟通。

这个checklist需要经验的积累或借鉴别人经验的结晶,根据编程语言有所不同,例如C++语言需要检查指针操作、内存的分配/释放等,而Java项目就无须检查这些。但基本编程原则的check是一致的,例如变量命名等。