1.命名規範 本系列的第一篇,命名風格本就是有關藝術審美,沒有美與醜的絕對標準,本文難免帶有主觀選擇傾向,但是會儘量保持客觀的態度歸納幾種主流的命名風格,僅供參考。制定規範是為了方便團隊溝通和利於代碼維護,雖然並不能符合每個藝術家的胃口。對於獨立開發者,花點時間設計自己的編碼風格也是有助於提高能力的
1.命名規範
本系列的第一篇,命名風格本就是有關藝術審美,沒有美與醜的絕對標準,本文難免帶有主觀選擇傾向,但是會儘量保持客觀的態度歸納幾種主流的命名風格,僅供參考。制定規範是為了方便團隊溝通和利於代碼維護,雖然並不能符合每個藝術家的胃口。對於獨立開發者,花點時間設計自己的編碼風格也是有助於提高能力的,至少可以在看到自己代碼的時候感覺美美噠~~。本文參考了<Google C++ 風格指南>,<Qt 編碼風格>,當然還有維基百科,以後不累述。1.1.常見命名法
蛇形命名法 [snake_case]: like_this,常見於Linux內核,C++標準庫,Boost以及Ruby,Rust等語言。 駝峰命名法 [camelCase]: likeThis,為了和帕斯卡命名法區分,本文特指小駝峰式命名法,常見於Qt以及Java。 帕斯卡命名法[PascalCase]: LikeThis,又名大駝峰式命名法,常見於Windows API函數以及C#。 匈牙利命名法[Hungarian notation]: dwWidth,系統匈牙利命名法是被黑的最多的,主要認為在有類型檢查的語言里發現類型錯誤編譯器比人更可靠;在有IDE的情況下,找到一個變數的類型也不是一件難事;通常我們看到一個陌生的變數的時候,如果不知道它是乾什麼的,知道它的類型好像也並沒有什麼用;並且在重構的時候,如果你要改變一個變數的類型,儘管其功能並沒有變,你還是要去修改變數名。所以除非是Windows系統開發,不建議使用系統匈牙利命名法。 rwPosition,匈牙利應用命名法不表示變數的類型,而是用首碼表示變數的目的,或者它代表了什麼。這種變數命名方法在幫助程式員理解變數的用途上是很有幫助的。但是建議首碼不要使用縮寫,除非所用的縮寫是普遍共識。1.2.文件命名
文件名尾碼:1 # C語言不糾結 2 file.h & file.c 3 # C++ Group.1(註意C是大寫) 4 file.h & file.C 5 # C++ Group.2 6 file.hh & file.cc 7 # C++ Group.3 8 file.hpp & file.cpp 9 # C++ Group.4 10 file.hxx & file.cxxtip.1:c語言沒有選擇,以下僅討論c++; tip.2:各組合可以混搭,比如常見的file.cpp搭配file.h和Google風格的file.cc搭配file.h; tip.3:強迫症可以選擇不混搭的各組,這樣看起來有對稱感; tip.4:不要選擇第1組大寫C的尾碼,特別是在Windows這樣不區分大小寫的操作系統上; tip.5:一些尾碼名可能不被某些較老的編譯器或IDE所預設支持,例如vs2005預設沒有擴展.hh尾碼; tip.6:如果需要跨平臺,推薦選擇第3組,至少boost是這麼選的; 文件名命名:
1 # Teddy項目UserLog文件為例: 2 # Group.1 3 UserLog.c & TedUserLog.c 4 # Group.2 5 userlog.c & teduserlog.c 6 # Group.3 7 userlog.c & ted_userlog.c 8 # Group.4 9 user_log.c & ted_user_log.c 10 # Group.5 11 user-log.c & ted-user-log.ctip.1:如果需要將源碼直接發佈,可以使用項目名做首碼,防止鏈接時文件名衝突(msvc好像能自動重命名衝突的.obj文件,但是跨平臺程式不能依賴這個特性); tip.2:各組文件名風格都沒有明顯的缺點,但要註意在區分大小寫的系統上UserLog.c和userlog.c是兩個文件;
1.3.類型命名
1 /* 2 ** 基本數據類型的重定義,小寫比首字母大寫更有利於延長Shift壽命, 3 ** 但也更容易產生命名衝突。 4 */ 5 typedef unsigned char byte; 6 typedef unsigned char byte_t; 7 typedef unsigned char Byte; 8 typedef unsigned char Byte_t; 9 10 /* 11 ** 類與結構體常見的風格是採用PascalCase,不推薦使用camelCase 12 ** 這種怪異的風格。 13 */ 14 class HashTable { ... 15 class hash_table { ... 16 struct FileInfo { ... 17 struct file_info { ... 18 19 /* C語言常見到的風格還有結構體名稱加'_t'尾碼 */ 20 struct fileinfo_t { ... 21 struct FileInfo_t { ... 22 23 /* 枚舉命名常見PascalCase風格 */ 24 enum FileFlags { ... 25 enum file_flags { ...tip.1:c語言沒有命名空間,為防止命名衝突,常見做法是將項目名或其縮寫作為類型名稱首碼; tip.2:類,結構體,枚舉的命名風格儘量保持一致;
1.4.命名空間命名
1 /* 一般使用項目名稱,風格看喜好。 */ 2 namespace my_project { ... 3 namespace MyProject { ...
tip.1:確保命名空間不會和常用的庫衝突;
1.5.函數和變數命名
1 /* 2 ** 在函數和變數命名風格上PascalCase,camelCase, 3 ** snake_case三足鼎立,選擇憑喜好。 4 */ 5 void FunctionName(void) { ... 6 void functionName(void) { ... 7 void function_name(void) { ... 8 9 long VarName; 10 long varName; 11 long var_name; 12 13 /* 14 ** tip.1:snake_case在名稱比較長時可讀性較好; 15 */ 16 long variable_names_in_snake_case; 17 long VariableNamesInPascalCase; 18 long variableNamesInCamelCase; 19 20 /* 21 ** tip.2:PascalCase和camelCase在函數中的區分度較好, 22 ** 在快速掃描代碼邏輯的時候不易被其它符號所干擾。 23 */ 24 long FabonacciFunction(long rabbitNums) 25 { 26 if (rabbitNums < 2) { 27 return rabbitNums; 28 } 29 long resultOne = FabonacciFunction(rabbitNums - 1); 30 long resultTwo = FabonacciFunction(rabbitNums - 2); 31 return resultOne + resultTwo; 32 } 33 34 long fabonacci_function(long rabbit_nums) 35 { 36 if (rabbit_nums < 2) { 37 return rabbit_nums; 38 } 39 long result_one = fabonacci_function(rabbit_nums - 1); 40 long result_two = fabonacci_function(rabbit_nums - 2); 41 return result_one + result_two; 42 }
tip.3:如果類需要相容標準庫迭代器或是要支持range for,begin()和end()函數會破壞PascalCase風格的一致性;
1.6.類成員變數和全局變數命名
1 /* 2 ** 類成員變數和全局變數的命名風格和局部變數的命名風格 3 ** 並沒有更多的區別。唯一的問題是,是否要加首碼或尾碼 4 ** 以方便和局部變數區分開來。 5 */ 6 class UserInfo { 7 ... 8 private: 9 std::string user_name_; /* Google style */ 10 std::string m_userName; /* Hungarian notation */ 11 /* 不推薦首碼'_'的風格,可能會和標準庫命名衝突 */ 12 }; 13 14 /* 全局變數要少用,推薦加首碼用於區分 */ 15 extern "C" long g_commonCount;
tip.1:在有IDE提示時,首碼"m_"的類成員變數能夠很快被找到,如果不喜歡這種風格,"this->"同樣也很便利;
1.7.常量和枚舉值命名
1 /* 2 ** 常量和枚舉值的命名風格建議和局部變數的命名風格區分開, 3 ** 常見的有全字母大寫加'_'的風格,PascalCase風格,以及 4 ** Google加'k'首碼的風格。 5 */ 6 static const int DAYS_IN_WEEK = 7; 7 static const int kDaysInWeek = 7; 8 9 enum FileOpenMode { 10 ReadOnly, WriteOnly, ReadWrite 11 }; 12 13 enum FileOpenMode { 14 READ_ONLY, WRITE_ONLY, READ_WRITE 15 };
tip.1:如果可以使用c++11特性,推薦enum class,否則可以在有歧義的枚舉值中重覆枚舉類型的名字;
1.8.巨集命名
1 /* 巨集命名推薦使用全字母大寫加'_'分隔的風格 */ 2 #define OS_UNIX 3 #define OS_LINUX 4 #define OS_WINNT 5 6 /* 除非你想用條件編譯將某些功能變為可選項 */ 7 #ifdef USE_TCMALLOC 8 #define my_malloc tcmalloc 9 #else 10 #define my_malloc malloc 11 #endif
tip.1:能用常量替代巨集的地方儘量使用常量吧;