Motivation
源起

I have developed a lot of programs, so alought there is no one formal description, I already have one set of naming rules. Recently, I took apart in several group-developing projects. These exprements make me feel that: something such as naming is unnecessary (even awkward) if it is hardness; but is important to list them if you need a general direction.
雖然不能稱得上非常多,但是我個人開發過的程式還算不少,所以雖然沒有很正式的規定,但是已經有自己的一套命名規則;加上最近參加過幾次團體開發的經驗,覺得這種東西,硬性規定的確沒有必要,或者說,還蠻鳥的,不過提些大方向,尤其是條列出來,還蠻重要的。

This document will list several basic naming rules, maybe a few concepts about source code writing. In addition, I will suggest some minor issues, such as indenting. But just like many other documents on Internet, do that as a natural sequence is most important.
這份文件打算條列出一些基本的命名規則,或許還會寫寫一些關於原始碼的想法,什麼地方該怎麼寫,什麼地方不該怎麼寫;還有些更無關緊要的,像是縮排要幾格?我會提些建議,但是就像其他網路上文件提過的,自己習慣還是最重要的。

Variable Prefixes
變數前置字元

Prefix Meaning Description
g global Always used on global variables. But some global variable such as those in a library but that library doesn't provide any interface to access them, because they are global only in their own library, conceptually they are local in that module. So I will use m_ as a prefix on these variables.
通常使用在全域變數上,但是有些全域變數,像是一個函式庫的全域變數,因為它只在那個函式庫中全域,在概念上,我覺得反而比較像是那個模組裡的區域變數,所以這時我會選用 m 開頭,而不是使用 g 。
m module, member You could think them as module variables or member variables. But I like conceptual explanation more personally. So whenever I name an variable, not only class member variables will be prefixed by m_. Above situation is a example. Basically, only variables which span two or more modules will be prefixed by g_.
模組和成員變數,這兩種解釋都通,但因為我個人比較喜歡概念上的解釋,所以通常在使用上,不是只有在物件中(物件才有成員變數)才會用到 m 開頭的變數,上面提的例子就是一個,基本上,會超越模組(跨模組)使用的變數我才會以 g 開頭。
s static In principle, I will use s_ on those variables which are specified by static keyword (in C/C++). Of course, this kind of variables is rare. If you have a lot of s_ varialbes, there are two possible reasons: 1. your program is very special, or 2. you make a mistake! (maybe you confuse the concept of static variable.) Besides, some people like use st_ to be a prefix of static variables. Maybe st_ comes from static, but since one character will not confuse with other prefix characters, why we use two characters?
靜態變數,原則上,使用 static 這個關鍵字(在 C/C++ 語言中)的變數,我就會使用 s 開頭,當然,這在程式中是很少使用的,靜態變數多有兩種可能,一個是程式特殊,另一個就是你寫錯了!或是搞錯靜態變數的概念,基本上應該是不常用到才對;另外也有人喜歡用 st 開頭,取自 static 吧,不過既然一個字元就不會重複了,沒什麼必要用兩個字元。
local There is usually no any prefix before local variable. Here "local" means usually the area between two braces of functions. I list a identical variable in four representations: g_foo, m_foo, s_foo, and foo.
區域變數,通常前面是不會有任何前置字元的,而這邊所謂的區域,通常在函式的兩個大括號中間。這邊列出同一個變數,用四種表示法分別為 g_foo, m_foo, s_foo, foo 。

Variables Type
變數型態

Type Meaning Description
a array 老樣子,我還是喜歡邏輯上的意義,所以同樣是 int * 的型態,如果變數是代表著一個整數陣列,就用 a 開頭,若是代表著一個整數指標,則用 p 開頭。
ch char 字元型態,我不知道有沒有人只有 c 開頭的就是了。
d double 就目前來講,我希望所有浮點數都是倍精確度,所以只有定義 d 開頭的代表 double ,而沒有指定 float 所使用的縮寫。
f flag 其實應該就是布林代數,不過 C/C++ 語言中並沒有這個型態,我個人習慣使用 BOOL 來代表這個抽象型態;其實還有另一種命名法,就是使用 b 開頭代表 boolean ,然後 f 就可以用來代表 float ,但是至少目前我打算採用。
h handle, height 如果用過 handle 這種抽象型態的人,應該知道特地定出來是有其必要的,當然,如果沒用過,就別理它了;另外在不會搞混的情況下,代表高度的變數用 h 開頭也不錯。
i index, int 通常都用來當做索引變數,或是整數變數,雖然我比較喜歡前者,但是整數實在是太常用了,所以在我的程式碼中還是蠻常採用後者。
l long 長整數。
n number 通常用來代表量的變數,配合 i 使用不錯,例如 for (iFoo = 0; iFoo < nFoo; ++i) 。
p pointer 代表某種型態的指標,通常還會配合其他的型態。
sz string end of zero 以 NULL 結尾的字串型態,通常是 char * ,至於為什麼要叫 sz ,則是學別人的,也有人用 str (因為 string ),當然,也有人只有 s 開頭的(因為沒有別的型態衝突)。
t time_t 不一定是 time_t ,代表時間的型態應該都可以使用 t 開頭的變數。
u unsigned 無號數,通常會配合其他的型態一起使用。
w width 代表寬度的變數,通常會和 h 開頭一起用。

Variable Naming
變數命名

由於除了型態和前置字元之外,剩下部分的命名就跟英文沒什麼差別了,所以也無法一一列出,在這邊只會列出一些大方向,以及建議,沒有一定,重點有兩個,首先,自己要看得懂,用起來覺得方便(簡潔),再來,就是希望別人也能一眼就看出來,不然就失去了定標準的意義了。

  • 最簡單的,像是 i, j, x, y 還有 tmp 之類的變數,不用增加多餘的字元了。
  • 一定要使用之前的提的前置字元型態
  • 還有一套專門給 Windows Programming 的型態命名法,像是 wnd, bmp 之類的,可能有空再整理出來。
  • 對於不在上面所列的型態(前置字元應該不會有例外才對),取縮寫的方式如下
    • 刪母音,例如 region 可以縮成 rgn (這例子是學 MFC 的), table 可以縮成 tbl 。
    • 取前面數個字元,例如 prefix 可以縮成 pre , binary可以縮成 bin 。
    • 上面兩種,取意義比較明顯的那一個,像是 prefix 只取母音的話變成 prfx ?而 region 取前三個字元的話變成 reg ,太廣泛了,要想到 region 很難,我猜很多人會想到 register 吧?
    • 有時可以多取幾個字元,像是 function 縮成 fun 或許不怎麼樣,但是縮成 func 就不錯(也有人縮成 fn 就是了)。
    • 若是懶得想,或是都沒什麼意義,建議還是採用刪母音的方法。
    最後,能短就短,不過有時為了意義要表達清楚,最後整個單字都用上了也無可厚非,看個人喜好,在這邊是建議越簡潔越好。
  • 一個整數陣列要取成 aiFoo 還是 iaFoo 呢?我的習慣是前者,我覺得知道這個變數是一個 array 比知道每個元素是 int 要來得重要;它是一個陣列,而不是一個整數。
  • 同理 piFoo 和 ipFoo 我也是喜歡 piFoo ,因為說到底, piFoo 是一個指標,不是一個整數。
  • 那 paiFoo 跟 apiFoo 有什麼不同呢?前者代表一個指向(整數)陣列變數的指標;後者則是代表一個陣列變數,其中每個元素都是一個(整數)指標。這樣又有什麼不同?邏輯上不同罷了,程式碼都是 int * * ,不過在使用上會有差, (*paiFoo)[i] 跟 *(apiFoo[i]) 才是有意義的,而 *(paiFoo[i]) 跟 (*apiFoo)[i] 可能會使程式當掉。
  • 其他的部分,就把整個變數的意義直接用英文打出來即可;取縮寫的技巧可以參考上面提的。
  • 例如一個依據原子密度來排序的陣列,其中第 i 個元素表示第 i 個原子的密度是在所有原中子的名次,這個名次,我想用 int 就可以了,那麼這個陣列變數我會命名成 aiAtmDnstyRnk ;其中 Atm 代表原子( atom ),Dnsty 代表密度( density ),而 Rnk 代表排名 (Rank) ,至於順序則是用語言的習慣,"原子密度的排名",最後一個詞最為重要,通常在語法上是名詞,有人說英文是 rank of atom-density (rank of density of atom) ,這就真的看個人了,我喜歡把代表性的名詞放在最後,也可以放在最前,其他的順序,就真的不重要了,甚至去掉變成 aiRnk 也無妨(在不會混淆的情況下)。
  • 再強調一次,能短就短,有時取太長,還不如在宣告的地方加個註解來得清楚。

Function Prefixes
函式前置字元

Prefix Meaning Description
i inline inline functions, which are after "inline" keyword (in C++). Because inline functions are more efficient so I create the prefix character. Then whenever I want to call some functions, I could find inline functions first for efficiency.
擁有 inline 這個關鍵字的函式,這是只有在 C++ 中才有的, C 語言並沒有。另外,使用這個函式並沒有什麼特別,我當初定的原因只是因為 inline function 執行起來比較有效率,加上這個前置字元時,我會知道呼叫這個函式會比較有效率罷了。
m module, member You could think them as module functions or member functions. But I like conceptual explanation more personally. So whenever I name an function, not only class member functions will be prefixed by m_. Even some public class member functions, I wouldn't use m as their prefixes. Only pretected and private class member functions are prefixed by _m_. Besides, some functions in a library, although they are not class member functions, if that library doesn't provide a interface to access these functions (so-called module function), then I would use _m_ as their prefixes.
模組和成員函式,這兩種解釋都通,但因為我個人比較喜歡概念上的解釋,所以通常在使用上,不是只有在物件中(物件才有成員函式)才會用到 m 開頭的變數,事實上,在物件中若是 public 的成員函式,我依然不會加上 m 的前置字元,只有受保護的成員函式( protected, private )我才會用;而在某些函式庫中的函式,就算不是一個物件的成員函式,但是若是這個函式庫沒有提供此函式的介面給外界呼叫,如同 m 的變數一樣,我稱之為模組函式,應以 m 開頭。
s static In principle, I will use s_ on those functions which are specified by static keyword (in C/C++).
靜態函式,原則上,使用 static 這個關鍵字(在 C/C++ 語言中)的函式,我就會使用 s 開頭。
other There is usually no local functions. So global (so-called "other") functions are the most common. I list a identical function in four representations: _i_foo(), _m_foo(), _s_foo(), and foo().
通常函式是不分全域還是區域的,所以這邊所謂的其他,就是一般的全域函式。這邊列出同一個變數,用四種表示法分別為 _i_foo(), _m_foo(), _s_foo(), foo()

函式的前置字元應該是我自己定的,至少,我沒有參考過別人的文件;至於之所以變數的前置字元是 m_ 開頭,而函式則由 _m_ 開頭,這多一個底線的原因,主要是因為排序的關係,我希望同類的函式能排在一起,而是沒多這個底線的話,那麼所有模組函式可能會和一個 m 開頭的一般函式排在一起,我覺得很醜,所以才這樣定。

Function Naming
函式命名

函式命名和變數命名大同小異,除了函式不要求型態之外(沒看過有人要求,我目前也覺得還好),還有我自訂的函式前置字元,應該沒什麼特別的,但是下面還是列出一些在函式命名和變數命名上的差別。

  • 通常在 C 中,大家喜歡全小寫的函式名,中間用底線分開;例如 get_car_speed() 。
  • 通常在 C++ 中,大家喜歡用大寫的字來分隔單字;例如 GetCarSpeed() 。
  • 通常在 JAVA 中,大家喜歡用小寫開頭,但是又用大寫的字來分隔單字;例如 getCarSpeed() 。
  • 函式通常最重要的意義在動詞,放在最前面,像上面的例子"取得車子的速度",用這個順序幾乎沒有人會有意見。
  • 函式取縮寫的習慣似乎不怎麼普遍,完全不縮寫也蠻常見的,不過還是可以取,像是 rgb2hsv() (原本應該是 convert_red_green_blue_format_to_hue_saturation_value_format() 才對);其中 red 等縮成 r 蠻直覺的,而用 2 取代 to 更是常見;然後利用 to 的意義,進而省略 convert 也蠻直覺的。
  • 上面的例子,雖然很特別又有點極端,但是又說明了一次,能短就短,何況函式的註解相當重要,所以與其取一個長到懶得打的函式名,還不如在旁邊寫一個詳細的註解。

Indent
縮排