命名約定--Google Style Guide
阿新 • • 發佈:2018-12-30
最重要的一致性規則是命名管理. 命名的風格能讓我們在不需要去查詢型別宣告的條件下快速地瞭解某個名字代表的含義: 型別, 變數, 函式, 常量, 巨集, 等等, 甚至. 我們大腦中的模式匹配引擎非常依賴這些命名規則.
說明 儘可能使用描述性的命名, 別心疼空間, 畢竟相比之下讓程式碼易於新讀者理解更重要. 不要用只有專案開發者能理解的縮寫, 也不要通過砍掉幾個字母來縮寫單詞.
模板引數的命名應當遵循對應的分類: 型別模板引數應當遵循型別命名的規則, 而非型別模板應當遵循變數命名的規則.
2. 檔案命名
總述
檔名要全部小寫,可以包含下劃線(_)或連字元(-),依照專案的約定。如果沒有約定,那麼“_”更好。
說明
可接受的檔案命名示例:
不要使用已經存在於 /usr/include
下的檔名(即編譯器搜尋系統標頭檔案的路徑)
通常應儘量讓檔名更加明確。 http_sever_logs.h 就比 logs.h 要好。定義類時檔名一般成對出現,如 foo_bar.h 和 foo_bar.cc ,對應於類 FooBar 。
行內函數必須放在.h檔案中,如果行內函數比較短,就直接放在.h中。
3. 型別命名 總述 型別名稱的每個單詞首字母均大寫,不包含下劃線: MyExcitingClass,MyExcitingEnum。 說明 所有型別命名 —— 類 , 結構體 , 型別定義 ( typedef ), 列舉 , 型別模板引數 —— 均使用相同約定 , 即以大寫字母開始 , 每個單詞首字母均大寫 , 不包含下劃線 . 例如 :
說明
普通變數命名 舉例:
類資料成員 不管是靜態的還是非靜態的, 類資料成員都可以和普通變數一樣, 但要接下劃線.
說明 一般來說, 函式名的每個單詞首字母大寫 (即 “駝峰變數名” 或 “帕斯卡變數名”), 沒有下劃線. 對於首字母縮寫的單詞, 更傾向於將它們視作一個單詞進行首字母大寫 (例如, 寫作 StartRpc() 而非 StartRPC()).
取值和設值函式的命名與變數一致. 一般來說它們的名稱與實際的成員變數對應, 但並不強制要求. 例如 int count() 與 void set_count(int count).
7.名稱空間命名 總述 名稱空間以小寫字母命名. 最高階名稱空間的名字取決於專案名稱. 要注意避免巢狀名稱空間的名字之間和常見的頂級名稱空間的名字之間發生衝突.
頂級名稱空間的名稱應當是專案名或者是該名稱空間中的程式碼所屬的團隊的名字. 名稱空間中的程式碼, 應當存放於和名稱空間的名字匹配的資料夾或其子資料夾中.
注意不使用縮寫作為名稱的規則同樣適用於名稱空間. 名稱空間中的程式碼極少需要涉及名稱空間的名稱, 因此沒有必要在名稱空間中使用縮寫.
要避免巢狀的名稱空間與常見的頂級名稱空間發生名稱衝突. 由於名稱查詢規則的存在, 名稱空間之間的衝突完全有可能導致編譯失敗. 尤其是, 不要建立巢狀的 std 名稱空間. 建議使用更獨特的專案識別符號 ( websearch::index, websearch::index_util) 而非常見的極易發生衝突的名稱 (比如 websearch::util).
對於 internal名稱空間, 要當心加入到同一 internal名稱空間的程式碼之間發生衝突 (由於內部維護人員通常來自同一團隊, 因此常有可能導致衝突). 在這種情況下, 請使用檔名以使得內部名稱獨一無二 (例如對於 frobber.h, 使用 websearch::index::frobber_internal).
8.列舉命名 總述 列舉的命名應當和常量或巨集 一致: kEnumName 或是 ENUM_NAME.
說明 單獨的列舉值應該優先採用常量的命名方式. 但巨集方式的命名也可以接受. 列舉名UrlTableErrors(以及 AlternateUrlTableErrors) 是型別, 所以要用大小寫混合的方式.
9.巨集命名 總述 你並不打算使用巨集, 對吧? 如果你一定要用, 像這樣命名: MY_MACRO_THAT_SCARES_SMALL_CHILDREN .
說明 通常不應該使用巨集. 如果不得不用, 其命名像列舉命名一樣全部大寫, 使用下劃線:
命名規則具有一定隨意性, 但相比按個人喜好命名, 一致性更重要, 所以無論你認為它們是否重要, 規則總歸是規則.
1.通用命名規則 總述 函式命名, 變數命名, 檔案命名要有描述性; 少用縮寫.說明 儘可能使用描述性的命名, 別心疼空間, 畢竟相比之下讓程式碼易於新讀者理解更重要. 不要用只有專案開發者能理解的縮寫, 也不要通過砍掉幾個字母來縮寫單詞.
int price_count_reader; // 無縮寫 int num_errors; // "num" 是一個常見的寫法 int num_dns_connections; // 人人都知道 "DNS" 是什麼
int n; // 毫無意義.
int nerr; // 含糊不清的縮寫.
int n_comp_conns; // 含糊不清的縮寫.
int wgc_connections; // 只有貴團隊知道是什麼意思.
int pc_reader; // "pc" 有太多可能的解釋了.
int cstmr_id; // 刪減了若干字母.
注意, 一些特定的廣為人知的縮寫是允許的, 例如用
i
表示迭代變數和用
T
表示模板引數.模板引數的命名應當遵循對應的分類: 型別模板引數應當遵循型別命名的規則, 而非型別模板應當遵循變數命名的規則.
2. 檔案命名
- my_useful_class.cc
- my-useful-class.cc
- myusefulclass.cc
- myusefulclass_test.cc// _unittest和_regtest已棄用
不要使用已經存在於 /usr/include
通常應儘量讓檔名更加明確。 http_sever_logs.h 就比 logs.h 要好。定義類時檔名一般成對出現,如 foo_bar.h 和 foo_bar.cc ,對應於類 FooBar 。
行內函數必須放在.h檔案中,如果行內函數比較短,就直接放在.h中。
3. 型別命名 總述 型別名稱的每個單詞首字母均大寫,不包含下劃線: MyExcitingClass,MyExcitingEnum。 說明 所有型別命名 —— 類 , 結構體 , 型別定義 ( typedef ), 列舉 , 型別模板引數 —— 均使用相同約定 , 即以大寫字母開始 , 每個單詞首字母均大寫 , 不包含下劃線 . 例如 :
// 類和結構體
class UrlTable { ...
class UrlTableTester { ...
struct UrlTableProperties { ...
// 型別定義
typedef hash_map<UrlTableProperties *, string> PropertiesMap;
// using 別名
using PropertiesMap = hash_map<UrlTableProperties *, string>;
// 列舉
enum UrlTableErrors { ...
4.變數命名
總述
變數 (包括函式引數) 和資料成員名一律小寫, 單詞之間用下劃線連線.類的成員變數以下劃線結尾, 但結構體的就不用,如: a_local_variable,a_struct_data_member,a_class_data_member_.
說明
普通變數命名 舉例:
string table_name; // 好 - 用下劃線.
string tablename; // 好 - 全小寫.
string tableName; // 差 - 混合大小寫
類資料成員 不管是靜態的還是非靜態的, 類資料成員都可以和普通變數一樣, 但要接下劃線.
class TableInfo {
...
private:
string table_name_; // 好 - 後加下劃線.
string tablename_; // 好.
static Pool<TableInfo>* pool_; // 好.
};
結構體變數
不管是靜態的還是非靜態的, 結構體資料成員都可以和普通變數一樣, 不用像類那樣接下劃線:
struct UrlTableProperties {
string name;
int num_entries;
static Pool<UrlTableProperties>* pool;
};
5.常量命名
總述
宣告為
constexpr 或
const 的變數, 或在程式執行期間其值始終保持不變的,
命名時以 “k” 開頭, 大小寫混合. 例如:
const int kDaysInAWeek = 7;
6.函式命名
總述
常規函式使用大小寫混合, 取值和設值函式則要求與變數名匹配:
MyExcitingFunction(), MyExcitingMethod(), my_exciting_member_variable(), set_my_exciting_member_variable()
說明 一般來說, 函式名的每個單詞首字母大寫 (即 “駝峰變數名” 或 “帕斯卡變數名”), 沒有下劃線. 對於首字母縮寫的單詞, 更傾向於將它們視作一個單詞進行首字母大寫 (例如, 寫作 StartRpc() 而非 StartRPC()).
AddTableEntry()
DeleteUrl()
OpenFileOrDie()
(同樣的命名規則同時適用於類作用域與名稱空間作用域的常量, 因為它們是作為 API 的一部分暴露對外的, 因此應當讓它們看起來像是一個函式, 因為在這時, 它們實際上是一個物件而非函式的這一事實對外不過是一個無關緊要的實現細節.)
取值和設值函式的命名與變數一致. 一般來說它們的名稱與實際的成員變數對應, 但並不強制要求. 例如 int count() 與 void set_count(int count).
7.名稱空間命名 總述 名稱空間以小寫字母命名. 最高階名稱空間的名字取決於專案名稱. 要注意避免巢狀名稱空間的名字之間和常見的頂級名稱空間的名字之間發生衝突.
頂級名稱空間的名稱應當是專案名或者是該名稱空間中的程式碼所屬的團隊的名字. 名稱空間中的程式碼, 應當存放於和名稱空間的名字匹配的資料夾或其子資料夾中.
注意不使用縮寫作為名稱的規則同樣適用於名稱空間. 名稱空間中的程式碼極少需要涉及名稱空間的名稱, 因此沒有必要在名稱空間中使用縮寫.
要避免巢狀的名稱空間與常見的頂級名稱空間發生名稱衝突. 由於名稱查詢規則的存在, 名稱空間之間的衝突完全有可能導致編譯失敗. 尤其是, 不要建立巢狀的 std 名稱空間. 建議使用更獨特的專案識別符號 ( websearch::index, websearch::index_util) 而非常見的極易發生衝突的名稱 (比如 websearch::util).
對於 internal名稱空間, 要當心加入到同一 internal名稱空間的程式碼之間發生衝突 (由於內部維護人員通常來自同一團隊, 因此常有可能導致衝突). 在這種情況下, 請使用檔名以使得內部名稱獨一無二 (例如對於 frobber.h, 使用 websearch::index::frobber_internal).
8.列舉命名 總述 列舉的命名應當和常量或巨集 一致: kEnumName 或是 ENUM_NAME.
說明 單獨的列舉值應該優先採用常量的命名方式. 但巨集方式的命名也可以接受. 列舉名UrlTableErrors(以及 AlternateUrlTableErrors) 是型別, 所以要用大小寫混合的方式.
enum UrlTableErrors {
kOK = 0,
kErrorOutOfMemory,
kErrorMalformedInput,
};
enum AlternateUrlTableErrors {
OK = 0,
OUT_OF_MEMORY = 1,
MALFORMED_INPUT = 2,
};
2009年1月之前, 我們一直建議採用巨集的方式命名列舉值. 由於列舉值和巨集之間的命名衝突, 直接導致了很多問題. 由此, 這裡改為優先選擇常量風格的命名方式. 新程式碼應該儘可能優先使用常量風格. 但是老程式碼沒必要切換到常量風格, 除非巨集風格確實會產生編譯期問題.
9.巨集命名 總述 你並不打算使用巨集, 對吧? 如果你一定要用, 像這樣命名: MY_MACRO_THAT_SCARES_SMALL_CHILDREN .
說明 通常不應該使用巨集. 如果不得不用, 其命名像列舉命名一樣全部大寫, 使用下劃線:
#define ROUND(x) ...
#define PI_ROUNDED 3.0
10.命名規則的特例
總述
如果你命名的實體與已有 C/C++ 實體相似, 可參考現有命名策略.