在軟件開發過程中,代碼的命名規範是一項很突出的內容。一套定義完整、結構清晰明瞭的命名規範將大大提升源代碼的可讀性和軟件的可維護性。
據考證,沒有一種命名規則可以讓所有的程序員都滿意,程序設計教科書一般也不會指定命名規則。但是制定一套令開發組成員基本滿意的命名規則,並在項目中貫徹實施,也是團隊開發一項必不可少的工作。
我將我的團隊的實際工作中的命名規則整理如下:
第一部分:共性規則
共有八項。作爲指導供成員採納。
【規則1】標識符應簡單明瞭,望文知意。
標識符采用英文單詞。切忌使用漢語拼音來命名。程序中的英文單詞一般不要太複雜,用詞應當準確。例如不要把CurrentValue寫成NowValue。
儘量不要使用單詞縮寫或首字母縮寫。只有當標識符過長時才考慮使用單詞縮寫。在使用縮寫時,不要自創縮寫,儘量使用被廣泛接受的縮寫。
【規則2】標識符長度應當符合“min-length && max-information”原則。
一般的講,長名字能更好地表達含義,所以函數名、變量名、類名長達十幾個字符不足爲怪。但是名字也不是越長越好。例如:變量名maxval就比maxValueUntilOverflow更好用。單字符的名字也是有用的,常見的如i,j,k,m,n,x,y,z等,它們通常用作函數內的局部變量。
【規則3】命名規則儘量與所採用的操作系統或開發工具的風格保持一致。
例如Windows應用程序的標識符通常採用“大小寫”混排的方式,如AddChild。而Unix應用程序的標識符通常採用“小寫加下劃線”的方式,如add_child。別把這兩類風格混在一起用。
【規則4】程序中不要出現僅靠大小寫區分的標識符。
例如:int x和int X;void foo() 和void FOO() 等。
【規則5】避免在不同級別的作用域中重名。
程序中不要出現標識符完全相同的局部變量和全局變量,儘管兩者因作用域的不同而不會發生語法錯誤,但會使人產生誤解。
【規則6】正確命名具有互斥意義的標識符。
使用正確的反義詞組命名具有互斥意義的變量或相反動作的函數。
如:"MinValue"和"MaxValue","GetName()" 和 "SetName()"
【規則7】儘量避免名字中出現數字編號。
如Value1,Value2等,除非邏輯上的確需要編號。這是爲了防止程序產生無意義的名字,降低程序的可讀性。
【規則8】使用庫標誌
在開發動態庫時,爲了防止軟件庫中的一些標識符和其它軟件庫中標識符衝突,可以爲各種標識符加上能反映軟件性質的前綴。
例如三維圖形標準OpenGL的所有庫函數均以gl開頭,所有常量(或宏定義)均以GL開頭。
第二部分:細則
我採用了一部分的“匈牙利”法命名規範,但沒有照搬。“匈牙利”法最大的特徵就是類型前綴。例如:
int nNum = 0; // n 爲類型信息,表明 nNum 是一個 int 類型
class CUser; // C 爲類型信息,表明 CUser 是一個類
但是正因爲如此,“匈牙利”法命名規範也給人一種繁瑣的感覺。例如:
int i, j, k;
float x, y, z;
倘若採用“匈牙利”命名規則,則應當寫成:
int iI, iJ, ik; // 前綴 i表示int類型
float fX, fY, fZ; // 前綴 f表示float類型
對於此類情況,我的處理方式是不加類型前綴。而對於下列情況我會加:
int iHeigh;
Bool bFlag;
總之,在我的命名規範中,類型前綴是一個可選的命名規則。下面分類進行詳細的規範。
一、 類和接口
1、 命名:類名都以大寫字母“C”開頭,後跟一個或多個單詞。每個單詞的首字母要大寫。接口以大寫"I"開頭,代表Interface。
2、 組成形式:推薦用"名詞"或"形容詞+名詞"的形式,例如:"CAnalyzer", "CFastVector" ....
二、 函數
1、 命名:函數的名稱由一個或多個單詞組成。每個單詞的首字母要大寫。最長不得超過20個字符。
2、 組成形式:全局函數應當使用"動詞"或者"動詞+名詞"(動賓詞組)的形式。例如:"gGetName()", " gDrawBox()"。
類成員函數應當只使用“動詞”,被省略掉的名詞就是對象本身。例如:
" box->Draw();"。
3、 全局函數:以小寫前綴"g"開頭。
4、 保護成員函數:開頭應當加上一個下劃線“_”以示區別,例如:"_SetState()"
5、 私有成員函數:開頭應當加上兩個下劃線“__”,例如:"__DestroyImp()"
6、 虛函數:習慣以“Do”開頭,如:"DoRefresh()", "_DoEncryption()"
7、 回調和事件處理函數 :習慣以單詞“On”開頭。例如:"_OnTimer()", "OnExit()"
三、 變量
變量是程序中使用最多的標識符,變量的命名規範是一套C++命名規範中最重要的部分:
1、 命名:變量名由作用域前綴+類型前綴+一個或多個單詞組成。變量用小寫字母開頭的單詞組合而成,第二個單詞的首字母要大寫。例如:int nDrawMode。變量最長不得超過20個字符。
特殊的:對於某些用途簡單明瞭的局部變量,也可以使用簡化的方式,如:i, j, k, x, y, z
2、 組成形式:變量的名字應當使用"名詞"或者"形容詞+名詞"。例如:"nCode", "m_nState","nMaxWidth"," oldValue "," newValue "。
3、 作用域前綴:作用域前綴標明一個變量的可見範圍。作用域可以有如下幾種:
前綴 |
說明 |
例子 |
無 |
局部變量 |
|
m_ |
類的成員變量(member) |
Int m_width |
ms_ |
類的靜態成員變量(static member) |
static int ms_initValue; |
s_ |
靜態變量(static) |
static int s_initValue; |
g_ |
外部全局變量(global) |
int g_howManyPeople; |
sg_ |
靜態全局變量(static global) |
|
gg_ |
進程間共享的共享數據段全局變量(global global) |
|
說明:作用域前綴不同於下面的類型前綴,應該堅決執行。原因是:
1)變量作用域和鏈接性改變的情況是很少的,例如,很少的情況下會把一個成員變量改成靜態變量
2)編程中使用的工具常常不會直觀的顯示變量的作用域和鏈接性
4、 類型前綴:作用域前綴標明一個變量的可見範圍。類型前綴標明一個變量的類型,有如下幾種:
前綴 |
說明 |
例子 |
b |
布爾型變量(bool, BOOL) |
bEnable |
ch |
字符型變量(char TCHAR) |
chName |
lpsz |
LPSTR、LPCSTR、LPCTSTR |
lpszName |
n |
整型和位域變量(int, UINT,__int32,__int64) |
nLength |
l |
long |
lOffset |
by |
BYTE |
|
w |
WORD |
wPos |
dw |
DWORD |
dwRange |
f |
浮點型變量(float) |
|
d |
double |
|
p |
指針型變量和迭代子(pointer) |
pDoc |
lp |
遠指針 |
|
e |
枚舉型變量(enumeration) |
|
pfn |
特別針對指向函數的指針變量和函數對象指針(pointer of function) |
|
g |
數組(grid) |
|
h |
handle Windows對象句柄 |
hWnd |
四、 常量
常量名由類型前綴+全大寫字母組成,單詞間通過下劃線來界定,如:cDELIMITER, nMAX_BUFFER。類型前綴的定義與變量命名規則中的相同。
五、 結構體、宏、枚舉變量、聯合體
全部由前綴+大寫字母組成,單詞間使用下劃線界定。
1、 結構體:加小寫前綴"tag",之後以大寫字母開頭。
例:
typedef struct tagPOINT
{
int x;
int y;
} POINT;
2、 宏:大寫字母組成,單詞間使用下劃線界定
例:#define MAXNUMBER 100
3、 枚舉變量:加小寫前綴"enum"。
例:
typedef enum _FILE_OPEN_MODE
{
OPEN_READONLY,
OPEN_READWRITE
}FILE_OPEN_MODE;
4、 聯合體:加小寫前綴"uni"。
例:
typedef union _VARIANT
{
char unichVal;
int uninVal;
float uniftVal;
} VARIANT;