收藏.Delphi.編碼規範

目錄
1.  一般的慣例(命名 - 縮進和空格 - 邊距 - 大小寫 - 註釋)
2.  語句(begin...end語句-if語句-case語句-for語句-while語句-repeat語句-with語句-異常處理語句)
3.  過程和函數(命名與格式-形參-變量-類型-自定義類型)
4.  面向對象相關(類的命名與格式-字段-方法-屬性-方法的實現)
制定編碼規範的目的是爲了使一組程序員生成同樣風格的代碼,使一個團隊形成並保持一定的風格。如果這個目標能夠實現,那麼整個項目的文件看上去就像是一個程序員寫的。好性很好玩,但這樣的好處是每個程序員的代碼都易於爲他人所理解,從而會在很大程度上提高代碼的可維護性,也因此會降低維護費用。對於任何團隊來說,這均是一個十分理想的境界。對於個人,選擇或自我生成一種編碼規範,並堅持這個規範,同樣會產生良好的效果。順便提一下這是一個十分誘人的目標,不過並不太難實現。 


目錄
1.  一般的慣例(命名 - 縮進和空格 - 邊距 - 大小寫 - 註釋)
2.  語句(begin...end語句-if語句-case語句-for語句-while語句-repeat語句-with語句-異常處理語句)
3.  過程和函數(命名與格式-形參-變量-類型-自定義類型)
4.  面向對象相關(類的命名與格式-字段-方法-屬性-方法的實現)
制定編碼規範的目的是爲了使一組程序員生成同樣風格的代碼,使一個團隊形成並保持一定的風格。如果這個目標能夠實現,那麼整個項目的文件看上去就像是一個程序員寫的。好性很好玩,但這樣的好處是每個程序員的代碼都易於爲他人所理解,從而會在很大程度上提高代碼的可維護性,也因此會降低維護費用。對於任何團隊來說,這均是一個十分理想的境界。對於個人,選擇或自我生成一種編碼規範,並堅持這個規範,同樣會產生良好的效果。順便提一下這是一個十分誘人的目標,不過並不太難實現。
每種程序設計語言都有屬於自己的編碼規範,編碼規範可以說是經驗的總結,當然也要借鑑其他的程序設計語言的規範。所以,向別人學習是十分重要的。其次,編碼規範的使用是爲了簡化程序員的工作,"簡化"的含義不是減少代碼量(相反,很多時候遵從規範會帶來更多的代碼),而是減少程序員在維護代碼時的勞動量。程序設計是一種非常複雜的工作,處理各種各樣的關係是令人生畏的,而且各種關係之間還有着千絲萬縷的聯繫。程序員應將大部分精力用來處理關係,而避免在過於細節的問題上浪費心機。如果他一眼就能夠明白程序的思路和結構,那麼對維護方案就會很快形成。而且,編碼規範應該是一個非常人性化的規範,你可以參考,也可以修改,但是要保證易於使用。但是在一個小組中要保證大家使用同樣的規範。程序設計是非常靈活的工作,只有靈活的思考,靈活的應用,纔可能得到好的結果。另外,使用規範在很大程度上是爲了減少程序員的記憶負擔。人的思維能力是極其優秀的,而記憶則十分可憐,我們整天面對電腦,她要幫我們做得很重要的事情應該是記憶。所以儘可能發揮程序員的思維優勢是我們的目標之一。
最後,程序設計工具對編碼規範有很大的影響,這個影響來源於開發商的程序設計風格。同樣基於C++,在Microsoft Visual C++和Borland C++ Builder中我們不會使用完全相同的編碼規範。Microsoft和Borland有着各自不同的而且十分鮮明的風格。作爲用戶,我們可以在此基礎上有所改變,但是這是有限度的。其實,在做出對供應商和開發工具的選擇時,我們同時確定了我們未來的風格。
1. 一般的慣例
1.1   命名
命名的基本原則是名稱要能夠明確表示數據的功能。
Object Pascal支持長文件名。名稱應該使用動詞、名詞或二者的組合。絕對不可以使用Delphi中定義的保留字和關鍵字,而且儘量不要使用其他語言中定義的保留字和關鍵字。儘量使用完整的詞語而避免使用縮寫、前綴和後綴、下劃線或其它符號,不推薦使用匈牙利命名法。
命名規範是爲了確保名稱的可讀性。以匈牙利命名法爲代表的命名規範制定了許多前綴和後綴以表示數據的類型、作用域或其它各種屬性。在Delphi中,你當然可用這種方法,但是這不是推薦的方法。有個原因是這類命名規範帶來個太多額外的記憶任務,另外一個原因是由Delphi自身的特點決定的。Delphi的強制類型檢查會自動監測所有的變量使用狀況,所以只需要我們稍加留心(注意單詞的大小寫)而不必費勁的添加五花八門的前綴。另外,對數據的考慮要基於含義而不是類型或作用域,注意力應該放在放在程序結構、邏輯關係和設計思路上。所以在Delphi中只需要使用完整的詞語組合來命名,不要考慮其它,當然應該儘可能的保持簡潔。
在一些語句(比如for循環)中我們要用到若干個整形數作爲計數變量。在此可以簡單的使用i、j、k這三個字母作爲變量名稱。這是在Fortran語言中形成並被保留下來的習慣,事實證明這非常好用並且易於理解。當然,我們使用更有意義的名稱會產生更好的效果,比如:MyCounter。一般來說i、j、k三個字母已完全夠用了,否則應該劃分出更多的過程或函數。
下面是幾個例子:
1.  SongsList  //表明這是一個歌曲的列表,song使用複數表明歌曲不止一首
2.  SetCarColor  //表明這是一個設置汽車顏色的函數,若定義了一個TCar類,那麼在類中就使用SetColor作爲設置汽車顏色的函數成員。
另外要注意對布爾變量的命名。布爾變量的名稱要能夠明確的表示出True和False的含義。比如說記錄某文件是否存在的變量,使用IsFileExisted,就比使用FileExisted好。
最後,永遠不要將一個全局變量命名爲:Temp或Tmp,但是在過程或函數中如此命名還是允許的。其實對於這條規則存在一點爭議,在有的編碼規範中更爲嚴格,如此命名是絕對禁止的,即使是在過程或函數中。但是,很多時候這樣命名的確很方便,尤其對於過程或函數。如果作爲全局變量,很可能會出現類型不匹配的賦值語句,雖然此時編譯器會給你很大的幫助,但是難以避免細小錯誤的發生。總之,遵守此規則會產生較好的效果,但是在必要的情況下沒有什麼是要嚴格遵守的。
1.2   縮進和空格
每級之間要縮進兩個空格,這樣會使程序層次分明,錯落有致。千萬不要使用製表符,因爲製表符的寬度隨不同的設置和應用程序的不同而難以保持一致,可不要指望你的程序只在Delphi中察看。另外要注意編輯器的使用,如果你只選擇了Delphi,那麼沒有什麼問題;如果你同時還使用了Word等文本處理器,請注意要使用適當的字體,以確保每個字母、符號的寬度相同。用Word等文本處理器打印時,同樣要注意字體的選擇。
空格的使用同樣是爲了保持程序的整潔,是程序員能夠快速明白程序結構。下面是一些規範和相應的例子:
1. 每個單詞之間要留有一個空格。例如:for TMyClass = class(TObject)
2. 在"="、"<>"、">="、"<="左右要留有一個空格;在":="和":"右邊要留有一個空格,而左邊不留。例如:if a = b then a:= b;a: integer;
3. 保留字和關鍵字與左邊的符號間要留有一個空格,與右邊的符號間不留。例如:procedure ShowMessage; overload;
4. 括號的使用:在過程和函數的定義和調用中,括號與外部的單詞和符號之間不留空格;與內部的單詞之間不留空格。在if語句的條件判斷中,與and、or等保留字之間要使用空格。例如:function Exchange(a: integer; b: integer); if (a = b) and ((a = c) or (a = d)) then ... end;
1.3   邊距
Delphi編輯器在右邊大約第81個字符處留有一條暗線,實際上在Delphi的默認界面下,當分辨率在800*600時,最大化窗口將顯示到該暗線左邊4個字母處。因此,不要將源代碼寫到暗線之外,也就是說每行包括前面和中間的空格不要多於80個字符。如果語句過長,那麼換行完成,換行後要縮進兩個字符。這樣也易於打印,在Delphi中超過暗線的部分不會被打印。如果使用Word等文字處理軟件打印Delphi程序,超出的部分會調到下一行的首部,這樣打印出的程序將難以閱讀。所以,儘量在編寫代碼的時候做好一切調整,不要把這種工作留到打印的時候進行。
換行時要注意保持程序的可讀性,儘量保持完整的部分。作爲例子,如果函數過長,那麼再換行時要將某個完整的參數說明換行,而不要只將數據類型聲明換行。下面的前兩種寫法是正確的,後面的幾種寫法都是錯誤的:
function AdditonFiveInputNumber(a: integer; b: integer; c: integer; d: ineger;
e: integer): integer;                      //正確
function AdditonFiveInputNumber(
a: integer;
b: integer;
c: integer;
d: ineger;
e: integer): integer;                      //正確
function AdditonFiveInputNumber(a: integer; b: integer; c: integer; d:
ineger; e: integer): integer;              //錯誤
function AdditonFiveInputNumber(a: integer; b: integer; c: integer; d: ineger;
e: integer): integer;                           //錯誤
function AdditonFiveInputNumber(a: integer; b: integer; c: integer; d: ineger;
e: integer): integer;                       //錯誤
1.4   大小寫
所有的自定義名稱中的每個單詞的首字母要使用大寫,其它字母使用小寫。Delphi保留字和關鍵字要全部使用小寫。Delphi預定義函數的寫法與自定義名稱寫法相同。Delphi中的基本數據類型要使用小寫,擴展的類類型要的前兩個字母要大寫(類類型的首字母是"T")。下面是一些例子:
1.  自定義名稱:MyFavouriteSong, CarList;
2.  保留字:if (a = b) and ((a = c) or (a = d)) then ... end;
3.  Delphi預定義函數:ShowMessage('Everything all right');
4.  Delphi擴展類類型:MyStrings = TStrings.Create;
1.5   註釋
Delphi支持兩種註釋:塊註釋({})和單行註釋(//)。註釋的作用是爲了解釋程序的設計思路,幫助程序員儘快明白兩年前甚至昨天寫的程序的思路。這實際上是爲了解決記憶問題,大腦不該被過分作爲存儲器使用,在程序設計中永遠不要過分依賴大腦,而要儘可能藉助文字。所以說,註釋在程序設計語言中是十分重要的方面,儘管很多人(尤其是初學者,也包括相當數量的程序員)對此毫不介意,他們很少寫註釋。註釋的另外一個應用是在程序調試階段,比如說有兩個語句,事先並不知道哪一個更好,於是需要測試:將一條語句前放置"//"(也就是說將這條語句改爲註釋),運行另一條語句,然後再做相反的工作,我們就可以輕鬆做出選擇。如果是一組語句,那就用塊註釋,但一定注意要將"{"和"}"放在顯眼的位置,比如說放在單獨的上下兩行。下面是一些使用原則:
1. 多數情況下,在自定義變量、類型的前面放置註釋是有必要的。
2. 多數情況下,在單元文件頂部放置註釋是必要的。在此,註釋中要包含:文件名、創建日期、修改日期、作者、修改作者以及必要的描述。
3. 註釋要有意義,不要使用沒用的註釋。比如:
while i < 8 do
begin
  ...
  i:= i + 1;   //Add one to i
end;
註釋"//Add one to i"在此是毫無意義的,當然並不是說簡單的語句(類似於:i : = i + 1)就不需要註釋。因爲簡單的語句往往會起到十分重要的作用,所以,如果這條語句會使人產生疑問或者讓人難以理解,那麼就要將此語句的作用標記下來。
4. 不要試圖在註釋中創建組合圖案,除非你認爲這十分必要。因爲在保持圖案完整美觀的情況下修改註釋是非常困難的。。
5. 要區分臨時註釋和永久註釋,你可以用你的方法在註釋中放置特殊符號來區分。這樣的好處是易於查找。
6. 對語句的更改要映射到相應的註釋中。
7. 註釋與代碼間要留有明顯的間隔,要一眼就能夠分清楚哪是語句哪是註釋。可以將註釋放在代碼行的前一行、後一行或留有至少兩個空格緊跟在代碼的後面,但是在代碼與註釋在同一行時不要使代碼跟在註釋的後面,另外,不要將在註釋放在代碼中間。
2. 語句
2.1   begin...end語句
begin和end語句要獨佔一行,begin要與上一層的第一個字母對齊,也就是說在換行之後不要留任何空格而直接寫begin,end要與所對應的begin對齊。本規則可以用在任何地方。下面是正確的寫法:
for i:= 1 to 10 do
begin
  ...
end;
但在if語句中有個特例,如下:
if Condition then
begin
  ...
end
else begin
  ...
end;
這樣寫的原則是要保證程序足夠緊湊。語句分層的好處是使我們面對一個清晰的程序段,但是過分的、不盡合理的分層會使程序過於鬆散,這同樣是需要避免的。
2.2   if語句
將最有可能執行的情況放在then語句中,不太可能的情況放在else子句中。這樣對維護來說不會帶來多少幫助,但會使程序效率更高。
多級if語句的可讀性不強,所以應經盡能避免出現多級if語句。當多於5級時,就該考慮使用case語句代替if語句。
不要在if語句中使用不必要的括號。在源代碼中,括號除了語法作用外在就是在必要時對條件分段,以增加程序的可讀性。所以在if語句中,如果條件明瞭而且在語法上不需要括號,那麼就不要使用括號;如果條件過於複雜,那麼就使用幾個括號。總之,一切爲了清晰。
如果在if語句中有多個條件要測試,應按照計算的複雜度進行排列。比如有三個條件:Condition1、Condition2和Condition3。按照這個順序,複雜度依次上升,與就是說Condition1比Condition2快,Condition2比Condition3快,則if語句就這麼寫:
if Condition1 and Condition2 and Condition3 then
begin
  ...
end;
2.3   case語句
case語句中每種情況的常量應當按照字母或數字的順序排列。
每種情況的處理與語句不要行數太多,因爲這樣會使整個case語句過長。應該儘量使用過程或函數以減少case語句的複雜度。
case語句的else子句只用於處理默認情況或進行錯誤檢測。
2.4   for語句
循環語句共有三種:for語句、while語句和repeat語句。如果循環次數確定,那麼就使用for語句;如果在第一次循環之前要實現執行一次以獲得初始比較數值,那麼就使用repeat語句;其他情況基本上都可以使用while語句。實際上這三條語句可以覆蓋所有的循環需要,而且可以互相替代。
在Delphi中要注意,for語句中的循環變量不可以在循環體中被賦值。這是與Turbo Pascal不同的地方。
另外,在循環語句,尤其是多個循環嵌套使用的代碼中,要小心使用break和exit關鍵字。
2.5   while語句
建議不要使用exit來退出while循環。退出循環的最好方法是通過循環條件。如果在循環體中要考慮到意外處理,那麼就要搞清楚處理的方式和對相關變量的影響。
2.6   repeat語句
repeat語句類似於while語句,且遵循同樣的規則。
2.7   with語句
with語句是一類非常容易出錯的語句,使用with語句可以有效避免重複的輸入工作。但是這樣會使程序難以檢查。所以,不要隨便使用with語句,而且絕對不要使用帶有兩個或多於兩個對象或記錄的with語句。順便提一下,儘量不要隨便使用with語句的原因不是因爲易於出錯,而是因爲難以排錯。考慮下面的例子:
with Label1, Label2 do
begin
  ...
  Caption := "Delphi";
  ...
end;
這樣會出現什麼問題呢?因爲這條語句夾在衆多語句之中,所以當程序出現問題時很難搞明白是怎麼回事。
3. 過程和函數
3.1   命名與格式
(1)       過程和函數的名稱應當由一個或多個完整的單詞組成。名稱的首字母應當大寫,其後每個單詞的首字母也應當大寫,其它字母則小寫。如果名稱過長,可以考慮使用單詞的縮寫,但是要使用常用的縮寫,比如:Tmp、Str。對於使用英文簡寫的單詞或詞組要全部使用大寫字母,比如:ID、UTS。下面是幾個正確的寫法:GetUserID、InputPassword、FindUserListFile、ImportUserNameFromStr。
(2)       過程或函數的名稱應當能夠簡單的表示該過程或函數的行爲。使用動詞和名詞爲過程和函數命名,動詞表示行爲,而名詞表示行爲的對象或目的。根據慣例,設置輸入參數值的過程名要以Set爲前綴,讀取數值的函數名要以Get爲前綴。下面是幾個正確的命名:SaveToFile、ReadFromFile、SetUserID、GetUsersNumber。
3.2   形參
(1)       格式:形參的排列要按照日常慣用的順序,比如:姓名、性別、年齡。而且在此基礎上要儘可能地把同一類型的形參歸併在一起。例如:
procedure SetUserInformation(Name, ID: string; Age: integer);
(2)       命名:所有的形參的命名要能夠表達出該形參的用途。在合適的情況下,形參的名稱最好以大寫字母A爲前綴。
(3)       讀寫規則:Delphi中有const和var形參,分別表示了對形參的讀寫控制。在形參列表中最好能夠明確表示。
3.3   變量
(1)       使用規則:在程序的開始階段要對所有的變量賦予明確的數值。普通類型變量要選擇合適的數值;類的實例如果此時不需要創建,那麼就賦值爲NIL。所以,在主程序、過程或函數中要明確程序的初始化部分和程序的功能部分。
(2)       全局變量:在程序設計中,應該儘可能的避免使用全局變量。因爲在程序的很多地方有可能修改全局變量的值,如果缺乏良好的管理機制,這將會使程序變得十分脆弱。而實際上很難在一個成百上千行的程序中對全局變量進行有效的監控。如果要使用全局變量,那麼就儘可能在單元文件(.pas)的實現部分聲明該變量。這樣該變量就只在此文件中有效,而不會被其它文件訪問。將全局變量放在單元文件的接口部分是很危險的。
(3)       局部變量:局部變量用於例程內部,遵循其它變量的命名規則。而且應該在例程的入口處立即初始化變量。
3.4   類型
大小寫規則:因爲類型標誌符是保留字,所以應該全部小寫。對於引用的其他公司、組織或個人的數據類型則儘可能地保留原樣。
3.5   自定義類型
(1)       命名:對於自定義數據類型要以大寫字母T爲前綴,這樣可以分清自定義數據類型和變量。名稱的其它部分的命名遵守命名的一般慣例。
(2)       枚舉類型:枚舉類型的名稱應該能夠代表該枚舉類型的用途。枚舉類型的標誌符列表的前綴應該包含兩個或三個小寫字母,以彼此關聯,這些字母依次是組成枚舉類型名稱的單詞的首字母。例如:
TAlign = (alNone, alTop, alBottom, alLeft, alRight, alClient, alCustom);
4. 面向對象相關
4.1     類的命名與格式
首先,類的名稱應當能夠清晰表達類的用途;其次,類的名稱之前要以大寫字母T開頭,以表示這是一個自定義數據類型。在Delphi中,所有的類的祖先類都是TObject,在定義類中要明確表示出類的祖先類。也就是說,即使該類的祖先類是TObject,也要表明(在Delphi中如果不寫明類的祖先類,那麼就默認其祖先類爲TObject)。
例如:
type
  TCar = class(TObject)
  private
    ...
  protected
    ...
  public
    ...
  end
類的實例的名稱可以與類名相同,如果只有一個實例時就使用沒有前綴T的類名;如果有多個實例,那麼就另外在前面添加其他合適的單詞。
在一個單元文件中只可以定義一個類,而且單元文件的名稱要與去掉前綴T的類名相同。如果在一個單元文件中定義了多個類,那麼一個類就可以直接訪問另一個類的私有字段或受保護字段,而不管該字段是否定義爲只讀。單元文件使用類的名稱的目的是我們可以通過文件名直接察覺到類的大概,這樣便於使用。
4.2     字段
字段的命名與變量的命名遵從同樣的規則,但是要加上大寫字母F爲前綴,以表示這是一個字段。另外,字段名稱應該爲名詞,而且要注意單詞複數的使用(數組字段應當是複數,表示集合含義的字段也應該使用複數名稱)。
所有的字段必須爲私有,這樣就可以通過屬性來決定該字段在類的作用域之外的訪問屬性。這樣組的目的是保證類的封裝性。
字段名稱的排列要參照字段的含義。參考名片管理系統,對一張名片我們首先關心的是姓名,然後是性別,然後是年齡,然後是各種聯繫方式,如果更細緻一點就要考慮生日、家庭成員等。於是我們可以簡單的定義類:
type
  TBusinessCard = class(TObject)
  private
    FName: string;
    FSex: string;
    FAge: integer;
    FEmail: string;
    ...
  public
    ...
  end;
4.3     方法
方法的命名與過程和函數的命名遵從同樣的規則。對於讀寫某個字段的方法要使用Get或Set前綴加去掉前綴F的字段名作爲名稱,前綴Get表示讀,Set表示寫。如果希望某個字段具有隻讀屬性,那麼僅僅爲其定義Get爲前綴的方法並在屬性中將其關聯。
如果不希望一個方法被派生類覆蓋,就使用靜態方法;如果希望一個方法被派生類覆蓋就使用虛擬方法;如果類的方法要被多個派生類直接或間接的使用,就使用動態方法;如果一個類需要創建實例,那麼就不要使用抽象方法。
要注意方法的訪問屬性。類的外部接口通過方法實現,應當儘可能的使必要的方法作爲接口,其它的方法要定義爲私有方法。比如定義方法ExportNameList,其中有使用了一個子方法ExportName,如果不需要外部使用方法ExportName,那麼就將其定義爲私有方法,將ExportNameList定義爲公有方法。
方法的參數儘量以字母A爲前綴。如果某個方法使用參數:AName,那麼此方法很可能要用到字段FName或屬性Name,這樣在實現代碼中就不會將它們混淆。
在方法的定義中要將同樣用途或爲了實現同一目標的方法分爲一組,在一組的第一個方法的前面和最後一個方法後面各留上一個空行即可。
4.4     屬性
屬性作爲私有字段的訪問器,應該使用相應字段的名稱,但要去掉前綴F。
4.5     方法的實現
在方法的實現代碼中要注意字段的訪問方法。可以直接使用字段來訪問,也可以使用屬性。如果要對字段進行寫操作,那麼就直接使用字段;如果僅僅進行讀操作,那麼就使用屬性。其實,在任何條件下都使用字段也很值得考慮。
如果要在程序發表後要修改某個方法,那麼儘量不要改變現有的接口而通過修改實現代碼,或者提供新的接口方法來實現。
首先要實現類的constructor和destructor方法,然後按照方法的定義順序依次實現。

發佈了7 篇原創文章 · 獲贊 1 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章