Google C++編程風格指南(六):代碼注釋

來源:互聯網
上載者:User

注釋

注釋雖然寫起來很痛苦,但對保證代碼可讀性至為重要,下面的規則描述了應該注釋什麼、注釋在哪兒。當然也要記住,注釋的確很重要,但最好的代碼本身就是文檔(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 = 6;

 

6.實現注釋(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很不錯,有時候,注釋確實是為了標記一些未完成的或完成的不盡如人意的地方,這樣一搜尋,就知道還有哪些活要幹,日誌都省了。

本文來自編程入門網:http://www.bianceng.cn/Programming/cplus/201009/19338.htm

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.