代码注释规范-google版本
- 注釋
注釋雖然寫起來很痛苦,但對保證代碼可讀性至為重要,下面的規則描述了應該注釋什么、注釋在哪兒。當然也要記住,注釋的確很重要,但最好的代碼本身就是文檔(self-documenting),類型和變量命名意義明確要比通過注釋解釋模糊的命名好得多。
注釋是為別人(下一個需要理解你的代碼的人)而寫的,認真點吧,那下一個人可能就是你!
1. 注釋風格(Comment Style)
使用//?或/* */?,統一就好。
//?或/* */?都可以,//?只是用的更加廣泛,在如何注釋和注釋風格上確保統一。
2. 文件注釋(File Comments)
在每一個文件開頭加入版權公告,然后是文件內容描述。
法律公告和作者信息?:
每一文件包含以下項,依次是:
1) 版權(copyright statement):如Copyright 2008 Google Inc.?;
2) 許可版本(license boilerplate):為項目選擇合適的許可證版本,如Apache 2.0?、BSD?、LGPL?、GPL?;
3) 作者(author line):標識文件的原始作者。
如果你對其他人創建的文件做了重大修改,將你的信息添加到作者信息里,這樣當其他人對該文件有疑問時可以知道該聯系誰。
文件內容?:
每一個文件版權許可及作者信息后,都要對文件內容進行注釋說明。
通常,.h?文件要對所聲明的類的功能和用法作簡單說明,.cc?文件包含了更多的實現細節或算法討論,如果你感覺這些實現細節或算法討論對于閱讀有幫助,可以把.cc?中的注釋放到.h?中,并在.cc?中指出文檔在.h?中。
不要單純在.h?和.cc?間復制注釋,復制的注釋偏離了實際意義。
3. 類注釋(Class Comments)
每個類的定義要附著描述類的功能和用法的注釋。
// Iterates over the contents of a GargantuanTable. Sample usage:// GargantuanTable_Iterator* iter = table->NewIterator();// for (iter->Seek("foo"); !iter->done(); iter->Next()) {// process(iter->key(), iter->value());// }// delete iter;class GargantuanTable_Iterator {...}如果你覺得已經在文件頂部詳細描述了該類,想直接簡單的來上一句“完整描述見文件頂部”的話,還是多少在類中加點注釋吧。
如果類有任何同步前提(synchronization assumptions),文檔說明之。如果該類的實例可被多線程訪問,使用時務必注意文檔說明。
4. 函數注釋(Function Comments)
函數聲明處注釋描述函數功能,定義處描述函數實現。
函數聲明?:
注釋于聲明之前,描述函數功能及用法,注釋使用描述式("Opens the file")而非指令式("Open the file");注釋只是為了描述函數而不是告訴函數做什么。通常,注釋不會描述函數如何實現,那是定義部分的事情。
函數聲明處注釋的內容:
1) inputs(輸入)及outputs(輸出);
2) 對類成員函數而言:函數調用期間對象是否需要保持引用參數,是否會釋放這些參數;
3) 如果函數分配了空間,需要由調用者釋放;
4) 參數是否可以為NULL?;
5) 是否存在函數使用的性能隱憂(performance implications);
6) 如果函數是可重入的(re-entrant),其同步前提(synchronization assumptions)是什么?
舉例如下:
// Returns an iterator for this table. It is the client's// responsibility to delete the iterator when it is done with it,// and it must not use the iterator once the GargantuanTable object// on which the iterator was created has been deleted.//// The iterator is initially positioned at the beginning of the table.//// This method is equivalent to:// Iterator* iter = table->NewIterator();// iter->Seek("");// return iter;// If you are going to immediately seek to another place in the// returned iterator, it will be faster to use NewIterator()// and avoid the extra seek.Iterator* GetIterator() const但不要有無謂冗余或顯而易見的注釋,下面的注釋就沒有必要加上“returns false otherwise”,因為已經暗含其中了:
// Returns true if the table cannot hold any more entries.bool IsTableFull()注釋構造/析構函數時,記住,讀代碼的人知道構造/析構函數是什么,所以“destroys this object”這樣的注釋是沒有意義的。說明構造函數對參數做了什么(例如,是否是指針的所有者)以及析構函數清理了什么,如果都是無關緊要的內容,直接 省掉注釋,析構函數前沒有注釋是很正常的。
函數定義?:
每個函數定義時要以注釋說明函數功能和實現要點,如使用的漂亮代碼、實現的簡要步驟、如此實現的理由、為什么前半部分要加鎖而后半部分不需要。
不要從.h?文件或其他地方的函數聲明處直接復制注釋,簡要說明函數功能是可以的,但重點要放在如何實現上。
5. 變量注釋(Variable Comments)
通常變量名本身足以很好說明變量用途,特定情況下,需要額外注釋說明。
類數據成員?:
每個類數據成員(也叫實例變量或成員變量)應注釋說明用途,如果變量可以接受NULL?或-1等警戒值(sentinel values),須說明之,如:
private:// Keeps track of the total number of entries in the table.// Used to ensure we do not go over the limit. -1 means// that we don't yet know how many entries the table has.int num_total_entries_全局變量(常量)?:
和數據成員相似,所有全局變量(常量)也應注釋說明含義及用途,如:
// The total number of tests cases that we run through in this regression test.const int kNumTestCases = 66. 實現注釋(Implementation Comments)
對于實現代碼中巧妙的、晦澀的、有趣的、重要的地方加以注釋。
代碼前注釋?:
出彩的或復雜的代碼塊前要加注釋,如:
// Divide result by two, taking into account that x// contains the carry from the add.for (int i = 0; i < result->size(); i++) {x = (x << 8) + (*result)[i];(*result)[i] = x >> 1;x &= 1;}行注釋?:
比較隱晦的地方要在行尾加入注釋,可以在代碼之后空兩格加行尾注釋,如:
// If we have enough memory, mmap the data portion too.mmap_budget = max<int64>(0, mmap_budget - index_->length());if (mmap_budget >= data_size_ && !MmapData(mmap_chunk_bytes, mlock))return; // Error already logged.注意,有兩塊注釋描述這段代碼,當函數返回時注釋提及錯誤已經被記入日志。
前后相鄰幾行都有注釋,可以適當調整使之可讀性更好:
...DoSomething(); // Comment here so the comments line up.DoSomethingElseThatIsLonger(); // Comment here so there are two spaces between// the code and the comment....NULL、true/false、1、2、3……?:
向函數傳入、布爾值或整數時,要注釋說明含義,或使用常量讓代碼望文知意,比較一下:
bool success = CalculateSomething(interesting_value,10,false,NULL); // What are these arguments??和:
bool success = CalculateSomething(interesting_value,10, // Default base value.false, // Not the first time we're calling this.NULL); // No callback.使用常量或描述性變量:
const int kDefaultBaseValue = 10;const bool kFirstTimeCalling = false;Callback *null_callback = NULL;bool success = CalculateSomething(interesting_value,kDefaultBaseValue,kFirstTimeCalling,null_callback);不要?:
注意永遠不要用自然語言翻譯代碼作為注釋,要假設讀你代碼的人C++比你強:D:
// Now go through the b array and make sure that if i occurs,// the next element is i+1.... // Geez. What a useless comment.7. 標點、拼寫和語法(Punctuation, Spelling and Grammar)
留意標點、拼寫和語法,寫的好的注釋比差的要易讀的多。
注釋一般是包含適當大寫和句點(.)的完整的句子,短一點的注釋(如代碼行尾的注釋)可以隨意點,依然要注意風格的一致性。完整的句子可讀性更好,也可以說明該注釋是完整的而不是一點不成熟的想法。
雖然被別人指出該用分號(semicolon)的時候用了逗號(comma)有點尷尬。清晰易讀的代碼還是很重要的,適當的標點、拼寫和語法對此會有所幫助。
8. TODO注釋(TODO Comments)
對那些臨時的、短期的解決方案,或已經夠好但并不完美的代碼使用TODO?注釋。
這樣的注釋要使用全大寫的字符串TODO?,后面括號(parentheses)里加上你的大名、郵件地址等,還可以加上冒號(colon):目的是可以根據統一的TODO?格式進行查找:
// TODO(kl@gmail.com): Use a "*" here for concatenation operator.// TODO(Zeke) change this to use relations.如果加上是為了在“將來某一天做某事”,可以加上一個特定的時間("Fix by November 2005")或事件("Remove this code when all clients can handle XML responses.")。
______________________________________
譯者:注釋也是比較人性化的約定了:
1. 關于注釋風格,很多C++的coders更喜歡行注釋,C coders或許對塊注釋依然情有獨鐘,或者在文件頭大段大段的注釋時使用塊注釋;
2.?文件注釋可以炫耀你的成就,也是為了捅了簍子別人可以找你;
3. 注釋要言簡意賅,不要拖沓冗余,復雜的東西簡單化和簡單的東西復雜化都是要被鄙視的;
4. 對于Chinese coders來說,用英文注釋還是用中文注釋,it is a problem,但不管怎樣,注釋是為了讓別人看懂,難道是為了炫耀編程語言之外的你的母語或外語水平嗎;
5. 注釋不要太亂,適當的縮進才會讓人樂意看,但也沒有必要規定注釋從第幾列開始(我自己寫代碼的時候總喜歡這樣),UNIX/LINUX下還可以約定是使用tab還是space,個人傾向于space;
6. TODO很不錯,有時候,注釋確實是為了標記一些未完成的或完成的不盡如人意的地方,這樣一搜索,就知道還有哪些活要干,日志都省了。
總結
以上是生活随笔為你收集整理的代码注释规范-google版本的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: GitHub user guide:He
- 下一篇: 深入理解傅立叶变换(详细)