[Clean Code] Chapter 4: 注释!

Comments 注释!

“Don’t comment bad code—rewrite it.”

​ —Brian W. Kernighan and P. J. Plaugher

当我们使用注释的时候,我们要承认我们的代码表达能力不够!


在代码中表达你的想法!

// 代码1
// Check to see if the employee is eligible for full benefits
if ((employee.flags & HOURLY_FLAG) &&
    (employee.age > 65)) {
    ...
}

VS

if (employee.isEligibleForFullBenefits()) {
    ...
}

最好的注释就是没有注释,就是用你的代码清晰的表达一切!


注释的目的

  • 提供有用的信息

    // 代码2
    // format matched kk:mm:ss EEE, MMM dd, yyyy
    Pattern timeMatcher = Pattern.compile("\\d*:\\d*:\\d* \\w*, \\w* \\d*, \\d*");

  • 解释某句,某段代码为什么那么写

    // 代码3
    //This is our best attempt to get a race condition
    //by creating large number of threads.
    for (int i = 0; i < 25000; i++) {
        WidgetBuilderThread widgetBuilderThread = new WidgetBuilderThread(widgetBuilder, text, parent, failFlag);
        Thread thread = new Thread(widgetBuilderThread);
        thread.start();
    }

注释可以清楚的解释某些比较模糊的函数

// 代码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

关于程序的警告

// 代码5
// 其他程序员看到此注释后,当他们修改代码时,他们不会犯错!
// 这就是这个注释的意义!
public static SimpleDateFormat makeStandardHttpDateFormat() {
    //SimpleDateFormat is not thread safe,
    //so we need to create each instance independently.
    SimpleDateFormat df = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z");
    df.setTimeZone(TimeZone.getTimeZone("GMT"));
    return df;
}

TODO

// 代码6
// TODO类型的注释告诉了reader 这个函数将会是什么,虽然由于一些原因现在不能写成那个样子
// TODO-MdM these are not needed
// We expect this to go away when we do the checkout model
protected VersionInfo makeVersion() throws Exception {
    return null;
}

什么是Bad 注释

看过注释之后,你还需要查看其他模块的代码才能明白注释的真正含义。那么,这样的注释就是bad comments!

  • 冗余的注释

    有些注释甚至比代码本身还长!!看下面的代码和注释

// 代码7
// 注释太长了,完全不必要
// Utility method that returns when this.closed is true. Throws an exception 
// if the timeout is reached.
public synchronized void waitForClose(final long timeoutMillis) throws Exception {
    if(!closed) {
        wait(timeoutMillis); 
        if(!closed)
            throw new Exception("MockResponseSender could not be closed"); 
    }
}
  • 可能产生误导的注释

    在代码7的注释中,有个小问题是 waitForClose并不是当closed变成true 返回,而是是true的时候返回。而且当其不是true,需要等待一段时间,如果仍不是true, 抛出异常。

  • 那些对函数每个参数的注释

    // 代码8
    /** *
    * @param title The title of the CD
    * @param author The author of the CD
    * @param tracks The number of tracks on the CD
    * @param durationInMinutes The duration of the CD in minutes */
    public void addCD(String title, String author,
        int tracks, int durationInMinutes) {
        CD cd = new CD(); 
        cd.title = title; 
        cd.author = author;
        cd.tracks = tracks; 
        cd.duration = duration; 
        cdList.add(cd);
    }

    这些注释其实基本无意义,而且导致整个代码看起来又臭又长- -。

  • 毫无意义的垃圾注释

    // 代码9
    /**
    * Returns the day of the month.
    *
    * @return the day of the month. 
    */
    public int getDayOfMonth() { 
        return dayOfMonth;
    }

    此注释没有提供任何有用的信息。

  • 对老旧不用代码的注释

    // 代码10
    InputStreamResponse response = new InputStreamResponse();
    response.setBody(formatter.getResultStream(), formatter.getByteCount());
    // InputStream resultsStream = formatter.getResultStream();
    // StreamReader reader = new StreamReader(resultsStream);
    // response.setContent(reader.read(formatter.getByteCount()));

    对于这类注释,一个很恶心人的地方在于,其他人在阅读这段代码的时候,会不敢删除这些代码,他们会想这些代码可能很重要,所以原作者没有删除他。所有不要出现这样的注释!!!(我自己在工作中也遇到这样的代码,只有当我把所有代码读完,把各个层的逻辑理清,我才敢删除和修改它们。)

  • 提供关于其他处的信息

    确保注释要注解的是它下面的代码。而不是提供其他处的信息。

  • 含糊不清的注释

    // 代码11
    /*
    * 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];

    这注释,看完依然不知道是什么意思,这就失去了注释的意义!


结语

尽量在代码中清晰表达你的意图,如果不能,请用比较简短的注释清晰精准的表达你代码的意图。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章