《編寫可讀程式碼的藝術》第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 Account11 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)不斷改進。