註釋 註釋 註釋毫無疑問是讓別人以最快速度瞭解你代碼的最快途徑,但寫註釋的目的絕不僅僅是"解釋代碼做了什麼",更重要的儘量幫助代碼閱讀者對代碼瞭解的和作者一樣多。 當你寫代碼時,你腦海裡會有很多有價值的信息,但當其他人讀你代碼時,這些信息已經丟失,他們所見到的只是眼前代碼。 註釋約定 註釋約定 如果 ...
-
註釋
註釋毫無疑問是讓別人以最快速度瞭解你代碼的最快途徑,但寫註釋的目的絕不僅僅是"解釋代碼做了什麼",更重要的儘量幫助代碼閱讀者對代碼瞭解的和作者一樣多。
當你寫代碼時,你腦海裡會有很多有價值的信息,但當其他人讀你代碼時,這些信息已經丟失,他們所見到的只是眼前代碼。
-
註釋約定
如果IDE提供註釋格式,則儘量使用IDE提供的格式,否則使用"//"來註釋。類、屬性和方法的註釋在Visual Studio中都使用輸入"///"自動生成的格式。
-
類註釋約定
/// <summary>
/// 類說明
/// </summary>
public class BinaryTree
-
類屬性註釋約定
/// <summary>
/// 屬性說明
/// </summary>
; }
-
方法註釋約定
/// <summary>
/// 方法說明
/// </summary>
/// <param name="parentNode">參數說明</param>
/// <returns>返回值說明</returns>
parentNode)
-
代碼間註釋約定
-
單行註釋,註釋行數<3行時使用
//單行註釋
-
多行註釋,2<註釋行數<=10時使用
/*多行註釋1
多行註釋2
多行註釋3*/
-
註釋塊,10<註釋行數時使用,用50個*
/***************************************************
* 代碼塊註釋1
* 代碼塊註釋2
* ......
* 代碼塊註釋10
* 代碼塊註釋11
***************************************************/
-
何時寫註釋的約定
-
以下三種情況我們需要在所有的類、類屬性和方法都必須按照上述格式編寫註釋
- 客戶方對代碼註釋重視程度較高
- 我們需要提供代碼註釋自動生成的API文檔。
- 目前編寫的是公共核心模塊
- 如果客戶方沒有對註釋特殊要求,那麼按照下文中討論的只在需要的地方加註釋。不要加無謂的註釋。
-
常用註釋標識的約定
這裡約定下以後團隊常用幾種註釋標識及含義:
//TODO: 我還沒有處理的事情
//FIXME: 已知的問題
//HACK: 對一個問題不得不採用比較粗糙的解決方案
//XXX: 危險!這裡有重要的問題
請團隊成員自行在Visual Studio中配置FIXME和XXX為高優先順序的Comments.
Steps: Tools->Options->Environment->Task List->Tokens->Add->OK
配置完成後,我們就能在Task List(Ctrl+w,t)視窗中的Comments選項中看到代碼中存在的任務了。
-
關於何時使用“///”和“//”的約定
a. 對於需要讓調用者知道的信息,使用“///”註釋,以便讓調用者能在調用時看到。
b. 對於代碼內部實現細節,需要維護者知道的註釋,使用“//”。減少調用者閱讀時間。
-
不需要的註釋
閱讀註釋會占用閱讀真實代碼的時間,並且每條註釋都會占用屏幕上的空間。所以我們約定所加的註釋必須是有意義的註釋,否則不要浪費時間和空間。
區別要不要寫註釋的核心思想就是:不要為那些能快速從代碼本身就推斷的事實寫註釋。
-
不要為了註釋而註釋
有些人可能以前的公司對於註釋要求很高,如"何時寫註釋"章節中的要求。所以很多人為了寫註釋而註釋。
再沒有特殊要求的情況下我們要禁止寫下麵這種沒有意義的註釋。
/// <summary>
/// The class definition for Account
/// </summary>
public class BinaryTree
{
/// <summary>
/// Total counts of the nodes
/// </summary>
public int NodesCount { get; private set; }
/// <summary>
/// All the nodes in the tree
/// </summary>
public List<BinaryNode> Nodes { get; set; }
/// <summary>
/// Insert a node to the tree
/// </summary>
/// <param name="node">the node you want insert into the tree</param>
node)
-
不要用註釋來粉飾糟糕的代碼
寫註釋常見的動機之一就是試圖來使糟糕的代碼能讓別人看懂。對於這種"拐杖式註釋",我們不需要,我們要做的是把代碼改的能夠更具有"自我說明性"。
記住:"好代碼>壞代碼+好註釋"
如下麵這段函數的註釋
//Enforce limits on the reply as stated in the request
//such as the number of items returned, or total byte size,etc.
reply)
既然知道這個函數名會讓人很難讀懂,那麼為什麼不直接改好名字呢?這樣所有調用這個函數的地方都能很快速知道這個函數的作用,不用再跟進來看函數的作用。
public void EnforceLimitsFromRequestOnReply(Request request,Reply reply)
-
日誌式註釋
有人喜歡在每次編輯代碼時,都在模塊開始處加一條註釋。這類註釋就像是一種記錄每次修改的日誌。在很久以前這種記錄對於維護還有意義。但是對於現在的源碼控制來說,這些記錄完全是冗餘的,需要完全廢除。
/***************************************************
* July-29-2014:Fix Bug-12345: Add new method to calculate nodes count
* July-20-2014:Fix Bug-11111: Add Insert new node method
* ......
* July-20-2014:Task-00001: Create BinaryTree class
***************************************************/
-
個人簽名
//Added By XXXX
有人認為這種註釋有助於不瞭解這段代碼含意的人和他討論。事實上確是這條註釋放在那一年復一年,後來的代碼和原作者寫的源碼越來越不一樣,和XXXX也越來越沒關係。
重申一下,TFS里都能看到這類信息,不要加在代碼里。
-
位置標識
//AddNodePlace1
//AddNodePlace2
有人喜歡在代碼註釋裡加入位置標識以方便他查找代碼的位置。
現在的IDE都集成了這些功能,如VS中可以使用Bookmark(Ctrl+b,t)。
不要將這類註釋加到代碼中。
-
註釋掉的代碼
直接把代碼註釋掉是非常令人討厭的做法。
其他人不敢刪掉這些代碼。他們會想代碼依然在這一定是有原因的,而且這段代碼很重要,不能刪除。而且每個閱讀代碼的人都會去看一下這些被註釋掉的代碼中是否有他們需要註意的信息。
這些註釋掉的代碼會堆積在一起,散髮著腐爛的惡臭。
-
需要的註釋
-
記錄你對代碼有價值的見解
你應該在代碼中加入你對代碼這段代碼有價值的見解註釋。
如: //出乎意料的是,對於這些數據用二叉樹比哈希表要快40%
//哈希運算的代價比左右比要大的多
這段註釋會告訴讀者一些重要的性能信息,防止他們做無謂的優化。
-
為代碼中的不足寫註釋
代碼始終在演進,並且在代碼中肯定會有不足。
要把這些不足記錄下來以便後來人完善。
如當代碼需要改進時:
//TODO:嘗試優化演算法
如當代碼沒有完成時:
//TODO:處理JPG以外的圖片格式
你應該隨時把代碼將來該如何改動的想法用註釋的方式記錄下來。這種註釋給讀者帶來對代碼質量和當前狀態的寶貴見解,甚至會給他們指出如何改進代碼的方向。
-
對意料之中的疑問添加註釋
當別人讀你的代碼的時候,有些部分可能讓他們有這樣的疑問:"為什麼要這樣寫?"你的工作就是要給這些部分加上註釋。
如:
// 因為Connection的創建很耗費資源和時間,而且需要多線程訪問,
// 所以使用多線程單例模式
public static Connection Instance
{
get
{
if(_instance==null)
{
lock (_lock)
{
if (_instance == null)
{
_instance = new Connection();
}
}
}
return _instance;
}
}
-
公佈可能的陷阱
當為一個函數或者類寫註釋時,可以這樣的問自己:"這段代碼有什麼出人意料的地方嗎?會不會被無用?"。基本上說就是你需要未雨綢繆,預料到別人使用你代碼時可能遇到的問題。如:
//XXX: 因為調用外部郵件伺服器發送郵件,所以耗時較長,請使用非同步方法調用以防止UI卡死。
public void SendEmail(string to, string subject, string body)
-
對於代碼塊總結性地註釋
對於代碼塊的總結性註釋可以使讀者在深入細節之前就能得到該代碼塊的主旨,甚至有時候都可以直接跳過該代碼塊,從而可以快速準確的把握代碼。
如讀者看到://下麵代碼使用了二分查找演算法來快速的根據用戶Id找到相應用戶
那麼他就可以快速理解下麵代碼的邏輯,否則自己看二分查找還是要用些時間的。