[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];

    這注釋,看完依然不知道是什麼意思,這就失去了註釋的意義!


結語

儘量在代碼中清晰表達你的意圖,如果不能,請用比較簡短的註釋清晰精準的表達你代碼的意圖。

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