1. 程式人生 > 實用技巧 >《編寫可讀程式碼的藝術》第5章 該寫什麼樣的註釋

《編寫可讀程式碼的藝術》第5章 該寫什麼樣的註釋

1. 什麼樣的註釋是不需要的

下面的例子中的全部註釋沒有提供任何新的資訊,所以沒有價值。

不要為能從程式碼中快速推斷的事實寫註釋。

 1 // The class definition for Account
 2 class Account {
 3     public:
 4     // Constructor
 5     Account();
 6     
 7     // Set the profit member to a new value
 8     void SetProfit(double profit);
 9     
10     // Return the profit from this Account
11 double GetProfit(); 12 };

2. 不要為了註釋而註釋

沒有價值的註釋:

1 // Find the Node in the given subtree, with the given name, using the given depth.
2 Node* FindNodeInSubtree(Node* subtree, string name, int depth);

如果想要在這注釋,最好能給出更多重要的細節:

1 // Find a Node with the given 'name' or return NULL.
2 // If depth <= 0, only 'subtree' is inspected.
3 // If depth == N, only 'subtree' and N levels below are inspected. 4 Node* FindNodeInSubtree(Node* subtree, string name, int depth);

3. 應當使用好的變數名,而不是給不好的名字加註釋

DeleteRegistry聽上去是一個危險的名字,註釋是為了澄清困惑
1 // Releases the handle for this key. This doesn't modify the actual registry.
2 void DeleteRegistry(RegistryKey* key);

倒不如直接使用一個能自我說明的名字

1 void ReleaseRegistryHandle(RegistryKey* key);

4. 記錄你的思想

(1)加入“導演評論”

// 出乎意料的是,對於這些資料,用二叉樹比用雜湊錶快40%
// 雜湊運算比左右比較大得多

上面的註釋會說明一條很重要的經驗,讓讀者不要為了無謂的優化浪費時間

1 // 作為整體可能會丟掉幾個詞,但這不是什麼問題。要100%解決太難了

上面的註釋說明了一個小問題不是bug,不用過多浪費時間修復。

1 // 這個類正變得越來越亂
2 // 也許我們應該建立一個子類ResourceNode來整理

上面的註釋鼓勵下一個人改正它,並給出了具體建議。

(2)為程式碼中的瑕疵寫註釋

標記           通常的含義
TODO:         有待處理的事情
FIXME:        已知的無法執行的程式碼
HACK:         對某個問題的粗糙的解決方案
XXX:          危險!這裡有問題

具體應遵循團隊的規範
(3)給常量加註釋

下面的註釋告訴讀者:常量值設定成1就太低了,50可能就太誇張了

const int NUM_THREADS = 8 // as long as it's >= 2 * num_processors, that's good enough.

可能常量的名字已經夠清楚,然而很多常量可以通過加註釋進行改進,只需記錄下當時的想法而已。

1 image_quality = 0.72; // users thought 0.72 gave the best size/quality tradeoff

5. 站在讀者的角度

(1)意料之中的提問

讀者可能會問為什麼不用data.clear(),可以在註釋中回答此問題

struct Recorder {
    vector<float> data;
    //...
    void Clear() {// Force vector to relinquish its memory (look up "STL swap trick")
        vector<float>().swap(data);
    }
};

(2)公佈可能的陷阱

這個函式可能會花一分鐘時間。如果沒有註釋,可能有人在不知情的情況下錯誤地呼叫這個函式,導致郵件伺服器宕機時,程式被掛起

// 呼叫外部伺服器來發送郵件。(1分鐘後超時)
void SendEmail(string to, string subject, string body);

(3)“全域性觀”註釋

對於新成員來講,最難的事情之一就是理解全域性觀。幾句精心選擇的話,比什麼都沒有強多了。

// 這個檔案包含一些輔助函式,為我們的檔案系統提供了更便利的介面
// 它處理了檔案許可權及其他基本的細節

(4)總結性註釋

下面的註釋很好地總結了低層程式碼

# Find all the items that customers purchased for themselves.
for customer_id in all_customers:
    for sale in all_sales[customer_id].sales:
        if sale.recipient == customer_id:
            #...

總結性註釋使得讀者可以在深入瞭解細節之前就能得到其主旨

5. 克服“作者心理阻滯”

很多程式設計師不喜歡寫註釋,因為要寫出好的註釋感覺好像要花很多功夫。通過一下方式可以克服這種心理:
(1)最好的辦法就是現在就開始寫,把心裡想的寫下來就好了,可能措辭會有些含糊,但是起碼比沒有強。
(2)讀一下這段註釋,看看也沒有什麼可以改進的地方。
(3)不斷改進。