代码整洁之道 读书笔记 - 第4章 注释

只有代码能告诉你它做的事,那是唯一真正准确的信息来源

注释是弥补在用代码表达意图时遭遇的失败

尽管有时也需要注释,我们也该多花心思尽量减少注释量

好注释

有些注释是必须的,也是有利的。不过要记住,唯一真正好的注释是想办法不去写的注释

1、法律信息

// Copyright (C) 2003,2004,2005 by Object Mentor, Inc. All rights reserved.
// Released under the terms of the GNU General Public License version 2 or later.

    公司代码规范要求编写与法律有关的注释。

2、提供信息的注释

//Returns an instance of the Responder being tested.
protected abstact Responder responderInstance();

    这类注释有时管用,但是更好的方式是尽量利用函数名称传达信息。比如,把函数重命名为responderBeingTested。

3、对意图的解释

//we are greater because we are the right type.
//This is our best attempt to get a race condition by creating large number of threads.

    不仅提供了有关实现的有用信息,而且还提供了某个决定后面的意图。

4、阐释

assertTrue(a.compareTo(a) == 0);    //a == a
assertTrue(a.compareTo(b) != 0);    //a != b
assertTrue(ab.compareTo(ab) == 0);    //ab == ab
assertTrue(a.compareTo(b) == -1);    //a < b
assertTrue(aa.compareTo(ab) == -1);    //aa < ab
assertTrue(ba.compareTo(bb) == -1);    //ba < bb
assertTrue(b.compareTo(a) == 1);    //b > a
assertTrue(ab.compareTo(aa) == 0);    //a == a
assertTrue(bb.compareTo(ba) == 0);    //a == a

    把某些晦涩难明的参数或返回值的意义翻译为某种可读形式。这也会冒阐释性注释本身就不正确的风险

5、警示

//Don't run unless you have some time to kiill.
//SimpleDateFormat is not thread safe, so we need to create each instance independently.

   警告其他程序员会出现某种后果

6、TODO注释

//TODO-MdM these are not needed We expect this to go away when we do the checkout model.

    //TODO形式在源代码中放置要做的工作列表

7、放大

// the trim is real important. It removes the starting spaces that could cause the item to be recognized as another list.

    用来放大某种看来不合理之物的重要性。

 坏注释

是糟糕的代码的支撑或借口,或者对错误决策的修正,基本上等于程序员自说自话。

1、喃喃自语

try
{
  ...
}
catch (IOException e)
{
  // No properties files means all defaults are loaded
}

  这段注释是什么意思?或许只有作者知道。

2、多余的注释

  对于一些简单函数,其头部位置的注释全属多余。读这些注释花的时间没准比读代码花的时间还要长。

3、误导性注释

  细微的误导信息,放在比代码本身更难阅读的注释里面,有可能导致其他程序员快活地调用并使自己陷于调试困境之中。

4、循规式注释

  不要公式化的给每个函数或每个变量添加注释。

5、日志式注释

  很久以前,在模块开始处创建并维护这些记录还算有道理。那时,我们还没有源代码控制系统可用。

* Changes (from 11-Oct-2001)
* --------------------------------
* 11-Oct-2001 : Re-organised the class and moved it to new package;
* 05-Nov-2001 : Added a getDescription() method, and eliminated NotableDate class;
* 12-Nov-2001 : IBD requires setDescription() method, now that NotableDate class is gone;
/* Added by Rick */

  如今,这种冗长的记录只会让模块变得凌乱不堪,应当全部删除。修改日志、作者这类注释就应该交给源代码控制系统。

6、废话注释

/**
*  Default constructor.
*/
protected AnnualDateRule() {
}
/** The name. */
private String name;
/** The version. */
private String version;
/** The licenceName. */
private String licenceName;
/** The version. */
private String info;

  这类注释,我们会视而不见,更可怕的是剪切-粘贴错误,作者在写注释时都没花心思,怎么能指望读者从中获益呢?

7、能用函数或变量时就别用注释

// does the module from the global list <mod> depend on the subsystem we are part of?
if (smodule.getDependSubsystems().contains(subSysMod.getSubSystem()))

  可以改成以下没有注释的版本

ArrayList moduleDependees = smodule.getDependSubsystems();
String ourSubSystem = subSysMod.getSubSystem();
if (moduleDependees.contains(ourSubSystem))

  先写注释再写代码,然后经过一次重构把注释去掉。

8、位置标记

// Actions //////////////////////////////////////////

  在源代码中标记某个特别位置,如果标记栏不多,效果还是显而易见。如果滥用标记栏,就会沉没在背景噪音中,被忽略掉。

9、括号后面的注释

public class wc {
  public static void main(String[] args) {
    ...
    try {
      while ((line = in.readLine()) != null) {
        ...
      }  // while
      ...
    }  // try
    catch (IOException e) {
      ...
    }  // catch
  }  // main
}

  在括号后面放置特殊的注释,尽管这对于含有深度嵌套结构的长函数可能有意义。如果发现自己想标记右括号,其实应该做的是缩短函数。

10、注释掉的代码

  有源代码控制系统,无需再用注释来标记,删掉即可,它们丢不了。

11、非本地信息

  假如一定要写注释,请确保它描述了离它最近的代码。别在本地注释的上下文环境中给出系统级的信息。

12、信息过多

  别在注释中添加有趣的历史性话题或者无关的细节描述

13、不明显的联系

  注释及其描述的代码之间的联系应该显而易见。如果不嫌麻烦要写注释,至少让读者能看着注释和代码,并且理解注释所谈何物

/*
* start with an array that is big enough to hold all the pixels
* (plus filter bytes), and an extra 200 bytes for header info
*/
this.pngBytes = new byte[((this.width + 1) * this.height * 3) + 200];

  过滤器字节是什么?与那个+1有关系吗?或与*3有关?还是与两者皆有关?为什么用200?注释的作用是解释未能自行解释的代码。如果注释本身还需要解释,就太遗憾了。

posted @ 2018-11-15 16:13  TanSea  阅读(244)  评论(0编辑  收藏  举报