IT干货程序员PMbook

读《编程匠艺—编写卓越的代码》:编写代码注释

2015-01-26  本文已影响337人  思学

查尔斯.普雷斯特.斯科特(Charles Prestwich Scott):
评论是自由的,但事实是神圣的

注释可以将优秀的代码和糟糕的代码区分开来,将艰涩难懂的逻辑与清晰友好的算法区分开。但我们也无须过分夸大注释的作用。如果说你的代码是蛋糕,那么你的注释就如同蛋糕上糖衣,它被精巧地涂抹以增加蛋糕的美感和价值,但不能掩饰蛋糕的裂缝和瑕疵。

一、什么是代码注释

二、注释标记

三、多少注释是恰当的

小威廉.斯特伦克(William Strunk Jr.):
铿锵有力之文必简洁

四、注释中应该有什么

贺瑞斯(Horace):
写好源头和本源是明智的做法

不好的注释比没有注释更糟糕,它们歪曲事实进而误导读者。

  1. 解释为什么,而不是怎么样
    (a).注释不是用来描述程序是怎样运行的,代码自己是其最权威的描述。
    (b).注释应该描述代码块起什么作用
    /* update WidgetList structure from GibWLRegistry*/这样的注释,不如写/* cache widget information for later*/。注释同一段代码,后者表达代码目的,而前者只告诉你这段代码做了什么。
    (c).注释可用来解释为什么代码要这么写。如有两种可供选择的实现方式,你决定采用其中一种,也许你该使用注释来解释一下,为什么你选择了这种实现方式。

  2. 不要取代或重复代码
    (a).如果注释描述的内容可以由编程语言本身实现,那么就试着用具体语句表达它。
    (b).如果你发现你用大量注释解释某个算法如何运行,请赶快停止,然后考虑是否需要重构代码或算法。
    (c).不要用注释描述变量的用法,重命名变量。
    (d).如果你要文档化一个应当总是成立的条件,也许你该写一个断言

  3. 确保注释有用
    注释的作用是标注和解释代码。注释需要满足:
    (a).记录意想不到的内容。如果代码有一部分是不常见、意想不到的,用注释记录下来;如果有特定问题需要规避,如一个操作系统问题,应该在注释中说明。
    (b).讲真话。不要写不准确的注释。
    (c).清晰明了。不要让注释模棱两可,内容尽量具体;不一定是完整的、语法正确的句子,但必须是可读的;避免缩写。
    (d).只关注当前代码,避免分心。不要记录过去我们怎么做;不要把应当剔除的代码(如旧代码)包含在注释中;避免使用ASCII艺术;不要在代码块结尾添加多余的注释,如在if语句的后括号后注释//end if

每当写完注释后,在代码上下文中回顾一遍这些注释,考虑一下:它们是否都是正确的信息,它们是否简洁,它们是否容易理解

五、实践

看看下面一小段C++代码:

for (int i = 0; i < wlst.sz(); ++i)
k(wlst[i])

很明显,你根本搞不懂这是在干吗。应用合理排版规则和添加注释说明对它进行改进:

// Iterate over all widgets in  the widget list
for (int i = 0; i < wlst.sz(); ++i)
{
        // print out this widget
        k(wlst[i]);
}

现在好多了,起码这段代码的目的清晰了。但它还是不太令人满足。使用恰当的函数名和变量重写代码:

for (int i = 0; i < widgets.size(); ++i)
       printWidget(widgets[i]);

再看代码,发现根本不需要注释,代码本身能自我描述了。

这印证了:

不要文档化差劲的代码——重写这些代码

六、注释的一些细节及其作用

根据你自己的品味,把下面的建议当作指导性的原则:

/* 
   * This is 
   * a block
   * comment.
   */

而不是这种

  /* 
This is 
        a block
comment.
  */
void strangeCommentStyle()
{
        for (int i = 0; i < JUST_ENOUGH; ++i)
        {
        //This is a meaning comment about the next line.
                  doSomethingMeaningful(i);
   // good comment 
                  doOtherOperation(i);
        }
}     

在不带括号的循环中,不要把注释放在单循环体语句之前,这会导致灾难性后果。

Class Point
{
public:
        ........
private:
        int x;                 //X轴坐标值
        int y;                 //Y轴坐标值
        int z;                 //Z轴坐标值
};

如果行尾注释直接跟在声明后面,代码看起来会显得拥挤,读起来更费劲。

/******************************************
 * class foo implementation
******************************************/

////////////////////////////////////////////////////

我们应当避免大量使用这种"分隔板"类的注释。将代码分组的应该是良好的缩进和结构,而不是生动的ASCII艺术。

八、总结

德尔莫.施瓦茨(Delmore Schwartz):
重要的写作是要讲眼之所见,这样就不必一遍又一遍的口口相传了

写高质量的注释比写高数量的注释更好,然而,最好的是写出高质量的代码——那些无需注释的自文档化代码。

上一篇 下一篇

猜你喜欢

热点阅读