GoogleCpp風格指南 6)命名約定

6 命名約定 Naming

最重要的一致性規則是命名管理govern naming; 命名風格快速獲取名字代表是什麼: 類型? 變量, 函數, 常量, 宏, ...甚至不需要去查找類型聲明; 大腦中的模式匹配引擎pattern-matching engine可以非常可靠的處理這些命名規則;

命名規則具有一定隨意性, 但相比按個人喜好命名, 一致性更重要, 所以不管你怎麼想, 規則總歸是規則;

6.1 通用命名規則 General Naming Rules

Tip 函數命名, 變量命名, 文件命名應局部描述性descriptive; 不要過度縮寫; 類型和變量應該是名詞, 函數名可以用"命令性"動詞;

儘可能給出描述性的名稱; 不要花心思去節省行空間, 讓你的代碼立刻能被理解要重要得多; 不要使用容易引起歧義的縮寫, 或者對項目外的讀者陌生的縮寫, 不要簡單地刪除幾個字符來做出一個簡寫名稱; 

1
2
int num_errors;                  // Good. "num" is a widespread convention.
int num_completed_connections;   // Good.

糟糕的命名使用含糊的縮寫或隨意的字符:

1
2
3
int n;                           // Bad - meaningless.
int nerr;                        // Bad - ambiguous abbreviation.
int n_comp_conns;                // Bad - ambiguous abbreviation.

類型和變量名一般爲名詞: 如 FileOpener, num_errors;

函數名通常是指令性的(確切的說它們應該是命令), 如 OpenFile(), set_num_errors(); 取值函數是個特例(在函數命名處詳細闡述), 函數名和它要取值的變量同名;

縮寫:

除非該縮寫在其他地方都非常普遍, 否則不要使用; 例如:

1
2
3
4
// Good
// These show proper names with no abbreviations.
int num_dns_connections;  // 大部分人都知道 "DNS" 是啥意思.
int price_count_reader;   // OK, price count. No abbreviation

WARNING

1
2
3
4
5
// Bad!
// Abbreviations can be confusing or ambiguous outside a small group.
int wgc_connections;  // Only your group knows what this stands for.
int pc_reader;        // Lots of things can be abbreviated "pc".
int cstmr_id;              // Deletes internal letters.

永遠不要用省略字母的縮寫:

1
2
int error_count;  // Good.
int error_cnt;    // Bad.


6.2 文件命名 File Names

Tip: 文件名要全部小寫, 可以包含下劃線 _ 或連字符 - , 按項目約定來; 如果原本沒有一致的規律, 建議用 "_";

可接受的文件命名:

1
2
3
4
my_useful_class.cc
my-useful-class.cc
myusefulclass.cc
myusefulclass_test.cc // _unittest and _regtest are deprecated.

C++文件要以 .cc結尾, 頭文件以 .h結尾;

[Add] 需要以文本textually形式包含到特定位置的文件應該以  .inc結尾; 參考self-contained headers <<

不要使用已經存在於 /usr/include下的文件名; (譯註: 即編譯器搜索系統頭文件的路徑), 如 db.h;

通常應儘量讓文件名更加明確; http_server_logs.h就比 logs.h要好; 定義類時文件名一般成對出現, 如 foo_bar.h和 foo_bar.cc, 對應於類 FooBar;

內聯函數必須放在 .h文件中; 如果內聯函數比較短, 就直接放在 .h中; 如果代碼比較長, 可以放到以 -inl.h 結尾的文件中; 對於包含大量內聯代碼的類, 可以使用三個文件:

1
2
3
url_table.h      // The class declaration.
url_table.cc     // The class definition.
url_table-inl.h  // Inline functions that include lots of code.

參考 -inl.h文件一節;


6.3 類型命名 Type Names

Tip  類型名稱的每個單詞首字母均大寫, 不包含下劃線underscore: MyExcitingClass, MyExictingEnum;

所有類型命名 -- 類, 結構體, 類型定義(typedef), 枚舉--均使用相同約定convention; [Add] 類型名字應該由一個大寫字母開始, 每個新單詞都以大寫字母開頭, 沒有下劃線<<<例如:

1
2
3
4
5
6
7
8
9
10
// classes and structs
class UrlTable { ...
class UrlTableTester { ...
struct UrlTableProperties { ...
 
// typedefs
typedef hash_map<UrlTableProperties *, string> PropertiesMap;
 
// enums
enum UrlTableErrors { ..


6.4 變量命名 Variable Names

Tip 變量名一律小寫, 單詞之間用下劃線連接; 類(而非結構體)的成員變量以下劃線結尾trailing underscore; 如:

[Add] a_local_variable, a_struct_data_member, a_class_data_member_ <<<

1
2
my_exciting_local_variable
my_exciting_member_variable_

普通變量命名 Common Variable names  

舉例: [下劃線會讓名字更長, 全小寫會有混淆出現: foot+ball -> football 類似]

1
2
string table_name;  // OK - uses underscore.
string tablename;   // OK - all lowercase.

WARNING: [why?打字麻煩?]

1
string tableName;   // Bad - mixed case.

[Add]

類數據成員 Class Data Members

對於類數據成員, static和non-static的, 都和普通非成員變量一樣命名, 但是以下劃線結尾;

1
2
3
4
5
6
7
class TableInfo {
  ...
 private:
  string table_name_;  // OK - underscore at end.
  string tablename_;   // OK.
  static Pool<TableInfo>* pool_;  // OK.
};

<<<

結構體變量 Struct Data Members

結構體的數據成員, static和non-static的, 可以和普通變量一樣, 不用像類那樣接下劃線:

1
2
3
4
5
struct UrlTableProperties {
  string name;
  int num_entries;
  static Pool<UrlTableProperties>* pool;
};

結構體與類的討論參考 Structs vs. Classes

全局變量 Global Variables

對全局變量沒有特別要求, 少用就好, 但如果你要用, 可以用 g_ 或其他標誌作爲前綴, 以便更好地區分局部變量;


6.5 常量命名 Constant Names

Tip 在名稱前加 k:  kDaysInAWeek; 混合大小寫, 對於在全局或類內定義的常量;

爲方便閱讀, 所有編譯時常量, 無論是局部的, 全局的還是類中的, 和其他變量稍微區別一下; k後接大寫字母開頭的單詞:

1
const int kDaysInAWeek = 7;

[Add] 這個約定對於local範圍的編譯時常量來說不是強制的, 那種情況下用一般命名規則也可以;<<<


6.6 函數命名

Tip 常規函數使用大小寫混合, 取值和設置函數則要求與變量名匹配: 

MyExcitingFunction(), MyExcitingMethod(), my_exciting_member_variable(), set_my_exciting_member_variable();

常規函數 Regular Functions

函數名的每個單詞首字母大寫, 沒有下劃線:

1
2
AddTableEntry();
DeleteUrl();

[Add] 如果函數會在一個error上崩潰crash, 你應該加上OrDiie, 這隻適用於會在產品代碼中使用, 而且error是在一般操作下合理發生的情況下;

1
OpenFileOrDie()

取值和設值函數  Accessors and Mutators

取值和設值函數((get and set)要與存取的變量名匹配; 這兒摘錄一個類, num_entries_ 是該類的實例變量;

1
2
3
4
5
6
7
8
9
class MyClass {
    public:
        //...
        int num_entries() const { return num_entries_; }
        void set_num_entries(int num_entries) { num_entries_ = num_entries; }
 
    private:
        int num_entries_;
};

其他非常短小的內聯函數名也可以用小寫字母, 例如: 如果你在循環中調用這樣的函數甚至都不用緩存其返回值, 小寫命名就可以接受;


6.7 名字空間命名 Namespace Names

Tip 名字空間用小寫字母命名, 並給予項目名稱和目錄結構: google_awesome_project; [小寫是爲了和類區分?]

關於名字空間的討論和如何命名, 參考Namespaces;


6.8 枚舉命名 Enumerator Names

Tip 枚舉的命名應當和 常量 或 宏 一致: kEnumName或是 ENUM_NAME;

單獨的枚舉值應該優先採用常量的命名方式; 但宏方式的命名也可以接受; 枚舉名 UrlTableErrors(或AlternateUrlTableErrors)是類型; 所以要用大小寫混合的方式;

1
2
3
4
5
6
7
8
9
10
enum UrlTableErrors {
    kOK = 0,
    kErrorOutOfMemory,
    kErrorMalformedInput,
};
enum AlternateUrlTableErrors {
    OK = 0,
    OUT_OF_MEMORY = 1,
    MALFORMED_INPUT = 2,
};

2009 Jan之前我們一直建議採用宏的方式命名枚舉值; 由於枚舉值和宏之間的命名衝突collision, 直接導致了很多問題; 因此, 這裏改爲優先選擇常量風格constant-style的命名方式; 新代碼應該儘可能優先使用常量風格; 但老代碼沒必要切換到常量風格, 除非宏風格確實會產生編譯期問題;


6.9 宏命名 Macro Names

Tip 你並不打算使用宏吧? 如果一定要用, 像這樣命名: MY_MACRO_THAT_SCARES_SMALL_CHILDREN

參考 預處理宏description of macros, 通常不應該使用宏; 如果不得不用, 其命名像枚舉命名一樣全部大寫, 使用下劃線;

1
2
#define ROUND(x) ...
#define PI_ROUNDED 3.0


6.10 命名規則的特例 Exceptions to Naming Rules

Tip 如果你命名的實體已有 C/C++實體相似analogous, 可參考現有命名策略convention scheme;

bigopen(): 函數名, 參照 open()的形式;

unit: typedef

bigpos: struct或 class, 參照 pos的形式;

sparse_hash_map: STL相似實體, 參照STL命名約定;

LONGLONG_MAX: 常量, 如同 INT_MAX;


---TBC---YCR


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章