Delphi代碼標準文檔
Revision 1.0.0.5
編者:
Riceball(
riceball@cq118.com)
本文主要基于“
Delphi Development Guide”一書(shū)的
代碼標準部分而來(lái),編者參考其它的Delphi代碼標準規范,以及結合現目前Delphi社區中流行的程序書(shū)寫(xiě)慣例,作了一些修改和裁剪,你也可以根據自己的需要進(jìn)行裁剪和修改。如果你有什么建議,或是希望編者加上你認為遺漏的東西,歡迎Email至:
riceball@cq118.com目錄:
前言源程序書(shū)寫(xiě)規范通用源代碼書(shū)寫(xiě)規范Object Pascal語(yǔ)句書(shū)寫(xiě)規范與用法命名規范過(guò)程(Procedure)與函數(Function)變量(Variable)類(lèi)型(Type)一般類(lèi)型構造類(lèi)型類(lèi)類(lèi)型(Class) 字段 方法 屬性
元件類(lèi)型窗體與對話(huà)框類(lèi)型數據模塊類(lèi)型文件項目文件(.dpr)窗體文件(.dfm)數據模塊文件遠程數據模塊文件單元文件(.pas) 普通單元 窗體單元 通用單元 元件單元
包文件(.dpk)源程序文檔注釋規范注釋文檔的一般規范單元文件注釋文檔格式函數(屬性)的注釋文檔格式Delphi代碼自動(dòng)格式化工具代碼標準文檔更新附錄:參考文獻1.
本文檔主要是為Delphi開(kāi)發(fā)人員提供一個(gè)源代碼書(shū)寫(xiě)標準,以及程序和文件的命名標準,使他們在編程時(shí)有一致格式可遵循。這樣,每個(gè)編程人員編寫(xiě)的代碼能夠被其他人理解。
本文檔還沒(méi)能包括代碼標準的每個(gè)細節,因此你可以在下面網(wǎng)址留意本文檔的最新版本:
http://dev.cq118.com/web/本文檔不包含用戶(hù)界面標準。用戶(hù)界面標準是獨立于其他標準的,并且同樣是重要的。
如果你有什么建議,或是希望編者加上你認為遺漏的東西,歡迎Email至:
riceball@cq118.com2.
2.1.
1). 縮進(jìn)
縮進(jìn)就是每級間有兩個(gè)空格。不要在源代碼中放置制表符。這是因為,制表符的寬度隨著(zhù)不同的設置和代碼管理實(shí)用程序(打印、文檔及版本控制等)而不同。
通過(guò)使用Tools|Environment 菜單,在Environment Options 對話(huà)框的General頁(yè)上,不要選中Use Tab Character 和Optional Fill 復選框,這樣,制表符就不會(huì )被保存。
2). 邊距
邊距設置為80個(gè)字符。源代碼一般不會(huì )因寫(xiě)一個(gè)單詞而超過(guò)邊距,但本規則比較靈活。只要可能,長(cháng)度超過(guò)一行的語(yǔ)句應當用逗號或運算符換行。換行后,應縮進(jìn)兩個(gè)字符。
3). begin...end 語(yǔ)句
begin 語(yǔ)句必須單獨占一行。例如,下面第一行是錯誤的,而第二行正確:
for i:=0 to 10 do begin // 錯, begin 與f o r 在同一行
for i:=0 to 10 do // 對, begin 在另外一行中
begin
本規則的一個(gè)特殊情況是,當begin 為else 語(yǔ)句的一部分時(shí),例如:
if some statement = then
begin
. . .
end
else begin
Some Other Statement;
end;
注意:end 語(yǔ)句總單獨一行。當begin 不為else 語(yǔ)句的一部分時(shí),相應的end 語(yǔ)句與begin 語(yǔ)句的縮進(jìn)量相同。
4).注釋
我們通常使用“{...}”類(lèi)型的塊注釋?zhuān)郧暗?#8220;(*...*)”類(lèi)型的塊注釋用于臨時(shí)注釋掉暫不使用的代碼,從Delphi 2開(kāi)始支持“//”行注釋?zhuān)绻麤Q定不在支持Delphi 2.0以下的版本,可以使用“//”注釋。
2.2.
1). 括號
在左括號與下一字符之間沒(méi)有空格。同樣,右括號與前一字符也沒(méi)有空格。下面的例子演示了正確與不正確的空格。
CallProc( Aparameter ); // 錯!
CallProc(Aparameter); // 正確!
不要在語(yǔ)句中包含多余的括號。在源代碼中,括號只有在確實(shí)需要時(shí)才使用。下面的例子演示了正確與不正確用法:
if (I=42) then // 錯,括號是多余的
if (I=42) or (J=42) then // 正確,必須使用括號
2). 保留字和關(guān)鍵字
Object Pascal 語(yǔ)言的保留字和關(guān)鍵字總是完全的小寫(xiě)。下面是Delphi 5保留字列表:
and
array
as
asm
begin
case
class
const
constructor
destructor
dispinterface
div
do
downto
else
end
except
exports
file
finalization
finally
for
function
goto
if
implementation
in
inherited
initialization
inline
interface
is
label
library
mod
nil
not
object
of
or
out
packed
procedure
program
property
raise
record
repeat
resourcestring
set
shl
shr
string
then
threadvar
to
try
type
unit
until
uses
var
while
with
xor
private
protected
public
publishedautomated
3). 過(guò)程和函數
(1). 格式
過(guò)程名應當以大寫(xiě)字母開(kāi)始,且大小寫(xiě)交錯以增加可讀性。下面是一個(gè)不正確的寫(xiě)法:
procedure thisisapoorlyformattedroutinename;
改成這樣寫(xiě)就對了:
procedure ThisIsMuchMoreReadableRoutineName;
(2). 形參
(1) 格式
只要可能,同一類(lèi)型的形參應當歸并在一起:
procedure Foo(Param1,Param2,Param3:Imteger;Param4:string);
(2) 參數順序
形參的順序主要要考慮寄存器調用規則。最常用的參數應當作為第一個(gè)參數,按使用頻率依次從左到右排。輸入參數位于輸出參數之前。范圍大的參數應當放在范圍小的參數之前。例如:
SomeProc(aPlanet, aContinent, aCountry, aState, aCity).
有些則例外。例如,在事件處理過(guò)程中,TObject 類(lèi)型的Sender 參數往往是第一個(gè)要傳遞的參數。
(3) 常量參數
要使記錄、數組、短字符串或接口類(lèi)型的參數不能被過(guò)程修改,就應當把形參標以Const 。這樣,編譯器將以最有效的方式生成代碼,保證傳遞的參數不可變。
如果其他類(lèi)型的參數希望不被過(guò)程所修改,也可以標上Const 。盡管這對效率沒(méi)有影響,但這給過(guò)程的調用者帶來(lái)了更多的信息。
4). 變量
(1). 局部變量
局部變量用于過(guò)程內部,果需要的話(huà),應當在過(guò)程的入口處立即初始化變量。局部的AnsiString 類(lèi)型的變量自動(dòng)被初始化為空字符串,局部的接口和dispinterface類(lèi)型的變量自動(dòng)被初始化為nil,局部的Variant和OleVariant類(lèi)型的變量自動(dòng)被初始化為Unassigned。
(2). 全局變量
一般不鼓勵使用全局變量。不過(guò),有時(shí)候需要用到。即使如此,也應當把全局變量限制在需要的環(huán)境中。例如,一個(gè)全局變量可能只在單元的實(shí)現部分是全局的。
全局數據如果將由許多單元使用,就應移動(dòng)到一個(gè)公用單元里被所有對象使用。全局數據可在聲明時(shí)直接初始化為一個(gè)值。注意,所有全局變量自動(dòng)進(jìn)行零初始化,因此,不要將全局變量初始化為諸如0 、nil、或Unassigned等空值。零初始化的全局變量在.EXE文件中不占空間。零初始化的數據保存在虛擬的數據段中,而虛擬數據段只在應用程序啟動(dòng)時(shí)才分配內存。非零初始化的全局數據則在.EXE文件中占空間。
5). 類(lèi)型
(1). 大小寫(xiě)規則
類(lèi)型標識符是保留字,應當全部小寫(xiě)。Win32 API 類(lèi)型常常全部大寫(xiě),并且遵循諸如Windows.pas或其他API單元中關(guān)于特定類(lèi)型名的規則。對于其他變量名,第一個(gè)字母應大寫(xiě),其他字母則大小寫(xiě)交錯。下面是一些例子:
var
MyString: string; // 保留字
WindowsHandle: HWND; // Win32 API 類(lèi)型
I: Integer; //在System單元中引入的類(lèi)型標識
(2). 浮點(diǎn)型
不鼓勵使用Real類(lèi)型,因為它只是為了與老的Pascal代碼兼容而保留的。通常情況下,對于浮點(diǎn)數應當使用Double。Double可被處理器優(yōu)化,是IEEE定義的標準的數據格式。當需要比Double提供的范圍更大時(shí),可以使用Extend。Extend是intel專(zhuān)用的類(lèi)型,Java不支持。當浮點(diǎn)變量的物理字節數很重要時(shí)(可能使用其他語(yǔ)言編寫(xiě)DLL),則應當使用Single。
(3).Variant和OleVariant
一般不建議使用Variant和OleVariant。但是,當數據類(lèi)型只有在運行期才知道時(shí)(常常是在COM和數據庫應用的程序中),這兩個(gè)類(lèi)型對編程就有必要。當進(jìn)行諸如自動(dòng)化ActiveX控件的COM編程時(shí),應當使用OleVariant;而對于非COM編程,則應當使用Variant。這是因為,Variant能夠有效地保存Delphi的原生字符串,而OleVariant則將所有字符串轉換為OLE字符串(即WideChar字符串),且沒(méi)有引用計數功能。
6). 語(yǔ)句
(1). If 語(yǔ)句
在if/then/else語(yǔ)句中,最有可能執行的情況應放在then子句中,不太可能的情況放在else子句中。為了避免出現許多if語(yǔ)句,可以使用case語(yǔ)句代替。如果多于5級,不要使用if語(yǔ)句。請改用更清楚的方法。不要在if語(yǔ)句中使用多余的括號。
如果在if語(yǔ)句中有多個(gè)條件要測試,應按照計算的復雜程度從右向左排。這樣,可以使代碼充分利用編譯器的短路估算邏輯。例如,如果Condition1比Condition2快,Condition2比Condition3快,則if語(yǔ)句一般應這樣構造:
if Condition1 and Condition2 and Condition3 then
如果Condition3為False的機會(huì )很大,利用短路估算邏輯,我們也可以將Condition3放在最前面:
if Condition3 and Condition1 and Condition2 then
(2). case 語(yǔ)句
(1) 概述
case語(yǔ)句中每種情況的常量應當按數字或字母的順序排列。每種情況的動(dòng)作語(yǔ)句應當簡(jiǎn)短且通常不超過(guò)4 - 5 行代碼。如果動(dòng)作太復雜,應將代碼單獨放在一個(gè)過(guò)程或函數中。Case語(yǔ)句的else子句只用于默認情況或錯誤檢測。
(2) 格式
case語(yǔ)句遵循一般的縮進(jìn)和命名規則。
(3). while 語(yǔ)句
建議不要使用Exit過(guò)程來(lái)退出while循環(huán)。如果需要的話(huà),應當使用循環(huán)條件退出循環(huán)。所有對while循環(huán)進(jìn)行初始化的代碼應當位于while入口前,且不要被無(wú)關(guān)的語(yǔ)句隔開(kāi)。任何業(yè)務(wù)的輔助工作都應在循環(huán)后立即進(jìn)行。
(4). for 語(yǔ)句
如果循環(huán)次數是確定的,應當用for語(yǔ)句代替while語(yǔ)句。
(5). repeat 語(yǔ)句
repeat語(yǔ)句類(lèi)似于while循環(huán),且遵循同樣的規則。
(6). with 語(yǔ)句
(1) 概述
with語(yǔ)句應小心使用。要避免過(guò)度使用with語(yǔ)句,尤其是在with語(yǔ)句中使用多個(gè)對象或記錄。例如:
with Record1,Record2 do
這些情況很容易迷惑編程人員,且導致調試困難。
(2) 格式
with語(yǔ)句也遵循本章關(guān)于命名和縮進(jìn)的規則。
7). 結構化異常處理
(1). 概述
異常處理主要用于糾正錯誤和保護資源。這意味著(zhù),凡是分配資源的地方,都必須使用try...finally來(lái)保證資源得到釋放。不過(guò),如果是在單元的初始/結束部分或者對象的構造器/析構器中來(lái)分配/釋放資源則例外。
(2). try...finally的用法
在可能的情況下,每個(gè)資源分配應當與try...finally結構匹配,例如,下面代碼可能導致錯誤:
SomeClass1 := TSomeClass.Create;
SomeClass2 := TSomeClass.Create;
try
{ do some code }
finally
SomeClass1.Free;
SomeClass2.Free;
end;
上述資源分配的一個(gè)安全方案是:
SomeClass1 := TSomeClass.Create;
try
SomeClass2 := TSomeClass.Create;
try
{ do some code }
finally
SomeClass2.Free;
end;
finally
SomeClass1.Free;
end;
但有時(shí)如果有許多類(lèi)都需要同時(shí)創(chuàng )建,上述方案就顯得非常累贅。這時(shí)候,我建議使用下述的一個(gè)安全方案:
SomeClass1 := nil;
SomeClass2 := nil;
SomeClass1 := TSomeClass.Create;
SomeClass2 := TSomeClass.Create;
try
{ do some code }
finally
FreeAndNil(SomeClass1);
FreeAndNil(SomeClass2);
end;
(3). try...except的用法
如果你希望在發(fā)生異常時(shí)執行一些任務(wù),可以使用try...except。通常,沒(méi)有必要為了簡(jiǎn)單地顯示一個(gè)錯誤信息而使用try...except,因為Application對象能夠自動(dòng)根據上下文做到這一點(diǎn)。如果要在子句中激活默認的異常處理,可以再次觸發(fā)異常。
(4). try...except...else的用法
不鼓勵使用帶else子句的try...except,因為這將阻塞所有的異常,包括你沒(méi)有準備處理的異常。
3.
3.1.
1).命名
過(guò)程與函數名應當有意義。進(jìn)行一個(gè)動(dòng)作的過(guò)程最好在名稱(chēng)前加上表示動(dòng)作的動(dòng)詞為前綴。例如:
procedure FormatHardDrive;
設置輸入參數值的過(guò)程名應當以Set 為其前綴,例如:
procedure SetUserName;
獲取數值的過(guò)程名應當以Get 為其前綴,例如:
function GetUserName:string;
2).形參
所有形參的名稱(chēng)都應當表達出它的用途。如果合適的話(huà),形參的名稱(chēng)最好以字母a 為前綴,例如:
procedure SomeProc(aUserName:string; aUserAge:integer);
當參數名與類(lèi)的特性或字段同名時(shí),前綴a 就有必要了。
3).命名沖突
當兩個(gè)單元中含有相同名稱(chēng)的過(guò)程時(shí),如果調用該過(guò)程,實(shí)際被調用的是Uses 子句中較后出現的那個(gè)單元中的過(guò)程。為避免這種情況,可在方法名前加想要的單元名,例如:
SysUtils.FindClose(SR);
或Windows.FindClose(Handle);
3.2.
變量的名稱(chēng)應當能夠表達出它的用途。循環(huán)控制變量常常為單個(gè)字母,諸如I 、J 或K 。也可以使用更有意義的名稱(chēng),例如UserIndex。布爾變量名必須能清楚表示出True 和False 值的意義。
1). 局部變量
局部變量遵循其他變量的命名規則。
2). 全局變量
全局變量以大寫(xiě)字母“G”打頭,并遵循其他變量的命名規則。
3.3.
3.3.1.
1). 枚舉型
枚舉類(lèi)型名必須代表枚舉的用途。名稱(chēng)前要加T字符作為前綴,表示這是個(gè)數據類(lèi)型。枚舉類(lèi)型的標識符列表的前綴應包含2 - 3 個(gè)小寫(xiě)字符,來(lái)彼此關(guān)聯(lián)。例如:
TSongType=(stRock, stClassical, stCountry, stAlternative, stHeavyMetal, stRB);
枚舉類(lèi)型的變量實(shí)例的名稱(chēng)與類(lèi)型相同,但沒(méi)有前綴T ,也可以給變量一個(gè)更加特殊名稱(chēng),諸如:FavoriteSongTypel、FavoriteSongType2等等。
3.3.2.
1). 數組類(lèi)型
數組類(lèi)型名應表達出該數組的用途。類(lèi)型名必須加字母“T”為前綴。如果要聲明一個(gè)指向數組類(lèi)型的指針,則必須加字母P 為前綴,且聲明在類(lèi)型聲明之前。例如:
type
PCycleArray = ^TCycleArray;
TCycleArray=array[1..100] of integer;
實(shí)際上,數組類(lèi)型的變量實(shí)例與類(lèi)型名稱(chēng)相同,但沒(méi)有“T”前綴。
2). 記錄類(lèi)型
記錄類(lèi)型名應表達出記錄的用途。類(lèi)型名必須加字母T為前綴。如果要聲明一個(gè)指向記錄類(lèi)型的指計,則必須加字母P為前綴,且其聲明在類(lèi)型聲明之前。例如:
type
PEmployee = ^TEmployee;
TEmployee = record
EmployeeName: string;
EmployeeRate: Double;
end;
3.3.3.
1). 命名與格式
類(lèi)的名稱(chēng)應當表達出類(lèi)的用途。一般的類(lèi)名前要加字母“T”,如果是接口類(lèi)那么類(lèi)名前要加“I”,錯誤異常類(lèi)的類(lèi)名前要加“E”,而類(lèi)引用類(lèi)型(Class-reference type)則要在類(lèi)名后加“Class”,抽象類(lèi)一般是在類(lèi)名前還要加“Custom”。例如:
type
TCustomCipher = class(TObject);
TCipher = class(TCustomCipher);
ICipher = interface;
TCipherClass = class of TCustomer
ECipherException = class(Exception);
類(lèi)的實(shí)例名稱(chēng)通常與類(lèi)名相同,只不過(guò)沒(méi)有前綴“T”。
var
Customer: TCustomer;
注意:關(guān)于元件的命名,請參閱“
元件類(lèi)型”。
2).字段
(1) 命名與格式
字段的命名遵循與變量相同的規則,只不過(guò)要加前綴F ,表示這是字段。
(2) 可見(jiàn)性
所有字段必須為私有。如果要在類(lèi)的作用域之外訪(fǎng)問(wèn)字段,可借助于類(lèi)的屬性來(lái)實(shí)現。
3).方法
(1) 命名與格式
方法的命名遵循與過(guò)程和函數相同的規則。
(2) 靜態(tài)方法
當你不希望一個(gè)方法被派生類(lèi)覆蓋時(shí),應當使用靜態(tài)方法。
(3) 虛擬方法(virtual)與動(dòng)態(tài)方法(dynamic)
當你希望一個(gè)方法能被派生類(lèi)覆蓋,應當使用虛擬方法(virtual)。如果類(lèi)的方法要被多個(gè)派生類(lèi)直接或間接地使用,則應當用動(dòng)態(tài)方法(dynamic)。例如,某一個(gè)類(lèi)含有一個(gè)被頻繁覆蓋的方法,并有100個(gè)派生類(lèi),則應將方法定義為動(dòng)態(tài)的,這樣可以減少內存的開(kāi)銷(xiāo)。
(4) 抽象方法(abstract)
如果一個(gè)類(lèi)要創(chuàng )建實(shí)例,則不要使用抽象方法。抽象方法只能在那些從不創(chuàng )建實(shí)例的基類(lèi)中使用。
(5) 屬性訪(fǎng)問(wèn)方法
所有屬性訪(fǎng)問(wèn)方法應當定義在類(lèi)的私有或保護部分。屬性訪(fǎng)問(wèn)方法遵循與過(guò)程和函數相同的規則。用于讀的方法應當加“Get”前綴,用于寫(xiě)的方法應當加“Set”前綴,并且有一個(gè)叫Value的參數,其類(lèi)型與屬性的類(lèi)型相同。例如:
TSomeClass = class(TObject)
private
FSomeField: Integer;
protected
function GetSomeField: Integer;
procedure SetSomeField(Value: Integer);
public
property SomeField: Integer read GetSomeField write SetSomeField;
end;
盡管不是必須,但還是建議你使用寫(xiě)訪(fǎng)問(wèn)方法來(lái)訪(fǎng)問(wèn)代表私有字段屬性。
4).屬性
屬性作為私有字段的訪(fǎng)問(wèn)器,遵循與字段相同的命名規則,只不過(guò)沒(méi)有F前綴。屬性名應為名詞,而不是動(dòng)詞。屬性是數據,而方法是動(dòng)作。數組屬性名應當是復數,而一般的屬性應當是單數。
3.3.4.
1).
元件的命名與類(lèi)的命名類(lèi)似,只不過(guò)當它與其它元件名稱(chēng)沖突時(shí),你可以加上3個(gè)字符的前綴,用以標識公司、個(gè)人或其他實(shí)體。例如,一個(gè)時(shí)鐘元件可以這樣聲明:
TddgClock = class(TComponent)
注意,作為前綴的3 個(gè)字符要小寫(xiě)。
2).
元件實(shí)例的名稱(chēng)應當能夠描述其實(shí)際意義,這里命名規則使用了一個(gè)變更的匈牙利前綴命名規范。使用前綴而不使用后綴的原因是在搜尋時(shí),在對象檢查器和代碼探索器中搜尋構件的名字比搜尋構件的類(lèi)型更容易。在這個(gè)標準中,元件實(shí)例名包括兩個(gè)部分:前綴和性質(zhì)標識名。
(1). 元件的前綴
元件的前綴多是表現元件類(lèi)型的字母縮寫(xiě)。參見(jiàn)下面表中的元件前綴:
元件類(lèi)名元件前綴
TActionList, TAction表示動(dòng)作的列表項act
TButton, TSpeedButton, TBitBtn等所有的按鈕類(lèi)btn
TCheckBox, TDBCheckBox等所有的檢查框chk
TRadioButton單選按鈕類(lèi)rdo
TToolBar工具條tb
TMainMenu所有的主菜單類(lèi)mm
TMainMenuItem所有的菜單項類(lèi)mi
TPopupMenu所有的彈出式菜單類(lèi)pm
TPopupMenuItem所有的彈出式菜單項類(lèi)pmi
TLabel, TStaticText等所有用來(lái)顯示的標簽類(lèi)lbl
TPanel等所有的面板類(lèi)pnl
TPageControl等所有的頁(yè)式控件類(lèi)pgc
TEdit, TMaskEdit等所有的單行編輯框類(lèi)edt
TMemo, TRichEdit等所有的多行編輯框類(lèi)mmo
TDrawGrid, TStringGrid等所有的網(wǎng)格類(lèi)grd
TAnimate等所有的動(dòng)畫(huà)類(lèi)ani
TImageList等所有的圖片列表類(lèi)il
TImage等圖片類(lèi)img
TChart圖表類(lèi)cht
TComboBox, TDBComboBox等所有的下拉式列表框類(lèi)cbo
TListBox, TDBList等所有的列表框類(lèi)lst
TTreeViewtv
TListViewlv
THotKeyhk
TSplitter等所有的分隔符類(lèi)spt
TOpenDialog等所有的對話(huà)框元件類(lèi)dlg
TTable等所有的數據表類(lèi)tbl
TQuery等所有的SQL查詢(xún)類(lèi)元件qry
TClientDataSet所有的客戶(hù)數據集元件cds
TDataSourceds
TDatabasedb
TSockConnection,TDCOMConnection等連接元件類(lèi)con
TQuickRep, TFastReport等所有的報表元件類(lèi)rpt
TDDEClientConv,TDDEClientItem等所有的DDE元件類(lèi)dde
TMonthCalendar等所有的日歷類(lèi)cal
TGroupBox等控件類(lèi)grp
如上所示,元件類(lèi)型前綴是從分析描述元件的類(lèi)型性質(zhì)而來(lái)的。通常情況下,下面的規則描述如何定義一個(gè)元件類(lèi)型前綴:
從元件類(lèi)型名中移去T前綴。例如TButton變成Button。 除了第一個(gè)元音,刪去所有元音字母。例如,Button變成bttn,Edit變成edt。 壓縮雙字母。例如,bttn變成btn。 如發(fā)生沖突,則在某一元件前綴中加入一個(gè)元音。例如在TBatton元件的前綴中加入元音變?yōu)閎atn,以區別TButton的前綴。
不過(guò),上述規則首先得保證前綴名稱(chēng)必須符合習慣,做到見(jiàn)名知意,如:TDDEClientConv控件的前綴就是一個(gè)例外。
注意:元件的前綴是為了表示出元件的類(lèi)型,是按鈕,還是標簽等等,因此沒(méi)有必要為每一個(gè)特別元件類(lèi)建立一個(gè)元件前綴,如: TMyButton的元件前綴仍為btn。
(2). 元件性質(zhì)標識名
元件性質(zhì)標識名是元件意圖的描述。例如,一個(gè)用于關(guān)閉窗體的TButton元件實(shí)例可命名為btnClose。一個(gè)編輯姓名的元件實(shí)例可命名為edtName。
3.3.5.
1).
窗體或對話(huà)框類(lèi)型的名稱(chēng)應當表達出窗體的用途,如果是窗體要加“Tfrm”前綴,如果是對話(huà)框要加“Tdlg”,后跟描述性名。例如,About窗體類(lèi)型名稱(chēng)為:
TfrmAbout = class(TForm)
主窗體的類(lèi)型名稱(chēng)為:
TfrmMain = class(TForm)
客戶(hù)登錄窗體的類(lèi)型名稱(chēng)為:
TfrmCustomerEntry = class(TForm)
登陸對話(huà)框的類(lèi)型名稱(chēng)為:
TdlgLogin = class(TForm)
2).
窗體實(shí)例的名稱(chēng)與相應的類(lèi)型名稱(chēng)相同,但沒(méi)有前綴T 。例如,前面提到的窗體類(lèi)型與實(shí)例的名稱(chēng)為:
類(lèi)型名實(shí)例名
TfrmAboutfrmAbout
TfrmMainfrmMain
TfrmCustomerEntryfrmCustomerEntry
TdlgLogindlgLogin
3).
除非特別原因,只有主窗體才自動(dòng)生成。其他所有窗體必須從Project Options對話(huà)框的自動(dòng)生成列表中刪除。更進(jìn)一步信息,請參閱后面幾節。
4).
所有窗體單元都應當含有實(shí)例化函數,用于創(chuàng )建、設置、模式顯示和釋放窗體。這個(gè)函數將返回由窗體返回的模式結果。傳遞給這個(gè)函數的參數遵循參數傳遞的規則。之所以要這樣封裝,是為了便于代碼的重用和維護。
窗體的變量應當從單元中移走,改在窗體實(shí)例化函數中作為局部變量定義(注意,要求從Project Options對話(huà)框的自動(dòng)生成列表中移走該窗體。請看前面的內容。
例如,下面的單元文件演示了GetUserData的實(shí)例化函數。
Unit UserDataFrm;
Interface
Uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
Type
TfrmUserData = class(TForm)
edtUserName: TEdit;
edtUserID: TEdit;
private
{ Private declarations }
public
{ Public declarations }
end;
function GetUserData(var aUserName: String;var aUserID: Integer): Word;
implementation
{$R *.DFM}
function GetUserData(var aUserName: String;var aUserID: Integer): Word;
var
frmUserData: TfrmUserData;
begin
frmUserData := TfrmUserData.Create(Application);
frmUserData.Caption:=‘Getting User Data‘ ;
Result : = frmUserData.ShowModal;
if Result=mrOK then
begin
aUserName := frmUserData.edtUserName.Text;
aUserID := StrToInt(frmUserData.edtUserID.Text);
end;
finally
frmUserData.Free;
end;
end;
End.
5).
如果一個(gè)窗體結構過(guò)于復雜,就必須將其分化成為一個(gè)主窗體框架以及嵌入到主窗體框架的若干子窗體框架。如:
TfrmMainFrame: TfrmInfoFrame,TfrmEditorFrame
使用窗體框架,主要是為了解決界面和代碼復用問(wèn)題,以及提高單元代碼的內聚力(劃分后,每一個(gè)窗體框架為一個(gè)獨立單元),從而提高軟件工程質(zhì)量。你必須提煉出界面關(guān)聯(lián)代碼(可復用的)和應用關(guān)聯(lián)代碼(不能復用的)。
3.3.6.
1). 數據模塊的命名標準
數據模塊類(lèi)型名稱(chēng)應表達出它的用途,且要加前綴“Tdm”,后跟描述性名稱(chēng)。例如,Customer數據模塊的類(lèi)型名稱(chēng)為:
TdmCustomer = class(TDataModule)
Orders 數據模塊的類(lèi)型名稱(chēng)為:
TdmOrder = class(TDataModule)
2). 數據模塊實(shí)例的命名標準
數據模塊實(shí)例的名稱(chēng)應當與相應的類(lèi)型名稱(chēng)相同,但沒(méi)有前綴T 。例如,前面的數據模塊類(lèi)型、實(shí)例名稱(chēng)如下:
類(lèi)型名稱(chēng)實(shí)例名
TdmCustomerdmCustomer
TdmOrderdmOrder
3.4.
建議在所有源文件、項目文件和單元文件使用結構化的文件頭信息。一個(gè)文件頭至少應包含以下信息:
{
Copyright @ Year by Authors
}
詳細說(shuō)明,請參閱:
單元文件注釋文檔格式。
3.4.1.
項目文件的名稱(chēng)應當具有描述意義。例如,“The Delphi 5 Developer’s Guide Bug Manager ”的項目名稱(chēng)為DDGBugs.dpr,一個(gè)系統信息程序的名稱(chēng)為SysInfo.dpr。
3.4.2.
窗體文件的名稱(chēng)應當表達出窗體的用途,且具有Frm后綴。例如,About窗體的文件名叫AboutFrm.dfm,主窗體的文件名叫MainFrm.dfm。
3.4.3.
數據模塊文件的名稱(chēng)應當表達出數據模塊的作用,且具有DM后綴。例如,Customers數據模塊的文件名叫CustomersDM.dfm。
3.4.4.
遠程數據模塊文件的名稱(chēng)應當表達出遠程數據模塊的用途。名稱(chēng)后要加RDM后綴。例如,Customers遠程數據模塊的文件叫CustomersRDM.dfm。
3.4.5.
1).
(1) 單元名
單元的名稱(chēng)應當有描述性。例如,應用程序的主窗體單元叫MaimFrm.pas。
(2) Uses 子句
Interface部分的Uses子句應當只包含該部分需要的單元。不要包含可能由Delphi自動(dòng)添加的單元名。Implementation部分的Uses子句應當只包含該部分需要的單元,不要有多余的單元。
(3) Interface 部分
Interface部分應當只包含需要被外部單元訪(fǎng)問(wèn)的類(lèi)型、變量、過(guò)程與函數的聲明。而且,這些聲明應當在Implementation部分之前。
(4) Implementation 部分
Implementation部分包括本單元私有的類(lèi)型、變量、過(guò)程與函數的實(shí)現。
(5) Initialization 部分
不要在Initialization部分放置花費時(shí)間很多的代碼。否則,將導致應用程序啟動(dòng)時(shí)顯得很慢。
(6) Finalization 部分
確保釋放所有在Initialization部分中分配的資源。
2).
窗體單元文件的名稱(chēng)與相應的窗體名稱(chēng)相同,只是要將前綴變成后綴。例如,About窗體的單元名稱(chēng)叫AboutFrm.pas。主窗體的單元文件名稱(chēng)叫MainFrm.pas。
3).
數據模塊單元文件的名稱(chēng)與相應的數據模塊名稱(chēng)相同。例如,數據模塊單元的名稱(chēng)叫CustomersDM.pas。
4).
通用單元是用于存放函數庫,一般類(lèi)型,或常量而非元件的單元。通用單元的名稱(chēng)應當表達出它的用途,名稱(chēng)前要加“u”前綴。例如,一個(gè)實(shí)用調試工具單元的名稱(chēng)叫uDebugUtilities.pas,包含全局變量的單元名稱(chēng)叫uCustomerGlobals.pas。
注意,一個(gè)項目中單元名稱(chēng)必須是唯一的。通用單元名不能重名。
5).
(1). 命名
元件單元應放在單獨的路徑中,以表明它們是定義元件的單元。它們一般與項目不放在同一路徑下。單元文件名稱(chēng)應表達出其內容。
注意,有關(guān)元件命名標準的更多信息,請參閱
“元件類(lèi)型的命名標準”。
元件單元只能含有一個(gè)主要元件,這是指出現在元件選項板上的元件。其他輔助性的元件或對象也可以包含在同一單元中。
(2). 注冊單元
元件的注冊過(guò)程應當從元件單元中移走,放在一個(gè)單獨的單元中。這個(gè)注冊單元用于注冊所有元件、屬性編輯器、元件編輯器、向導等。
元件注冊應當在設計期包中進(jìn)行。因此,注冊單元應當包含在設計期包而不是運行期包中。建議注冊單元這樣命名:
xxxReg.pas
其中,xxx字符前綴,以標識元件包名稱(chēng)或公司、個(gè)人、其他實(shí)體。例如,注冊單元命名為xxxReg.pas。
6).
(1). 運行期包與設計期包
運行期包中應當只包含所需要的單元。那些屬性編輯器和元件編輯器的單元應當放在設計期包中。注冊單元也應當放在設計期包中。
(2). 文件命名標準
包的命名遵循下列模式:
dcliiiDescvvCn.pkg —設計期包
iiiDescvvCn.pkg —運行期包
其中,iii代表一個(gè)2-3字符的前綴,用于標識公司、個(gè)人或其他需要標識的事情,也可不要;Desc表示該控件包的簡(jiǎn)短描述;vv代表包的版本號,你可以根據需要取舍;前綴“dcl”表示設計期包,沒(méi)有該前綴表示運行期包;字母“Cn”表示編譯器類(lèi)型與編譯器版本號,如:Delphi5=D5, Delphi4=D4, CBuilder3=C3...。
注意包名稱(chēng)中的lib或std分別表示這是設計期包還是運行期包。例如:
dclrbStdCompsD5.pkg —Delphi 5的設計期包
rbStdCompsD5.pkg —Delphi 5的運行期包
4.
我們將通過(guò)文檔(源程序文件聯(lián)機注釋?zhuān)┒x標準的Delphi 類(lèi)(函數等)的概要設計規范(official Delphi Class API Specification),以及定義Delphi 類(lèi)(函數等)的編程指南手冊。因此,我們可以以?xún)煞N方式來(lái)寫(xiě)程序文檔(注釋?zhuān)?,一是作為概要設計的規范,二是作為編程手冊。兩種程序文檔既有差別,又有它們共同的地方,因此,它們可以同時(shí)寫(xiě)在源程序文檔注釋中,它們兩者的差別在下面有說(shuō)明。
編寫(xiě) Delphi 概要設計規范
TODO: <略>
編寫(xiě)編程指南文檔
在概要設計規范的基礎上,增加了教程,例子程序,等等,并對目錄結構進(jìn)行了重新設計組織和整理。
為源程序的相關(guān)元素添加文檔注釋很簡(jiǎn)單,你只需要將注釋放在元素的聲明(Interface)部分(如果是接口函數或類(lèi)方法)或實(shí)現(implementation)部分(如果是私有函數)。例如:
(for Object Pascal)
{ The Sort function sorts the list.} function MyList.Sort(Options: Integer): BOOLEAN; begin [...] end;
(for C++)
// The Sort function sorts the list. bool MyList::Sort(int Options) { [...] }
注釋塊是由一系列的沒(méi)有被空行分開(kāi)的單行注釋構成的,下面就是一個(gè)注釋塊: // This is the first sentence. // This is the second, // and this the third
而下面的注釋則是兩個(gè)注釋塊,因為它們之間有一個(gè)空行把它們分開(kāi)了:
// This is the first sentence. // This is the second, // and this the third
許多文檔注釋分析工具(如:Doc-O-Matic)會(huì )將注釋塊內的所有的句子自動(dòng)連接在一起,形成一文字段落,如:
// This is the first sentence. // This is the second, // and this the third
經(jīng)過(guò)分析工具生成的文檔文本為:
This is the first sentence. This is the second, and this the third.
當注釋行前用“##”開(kāi)頭時(shí),該行注釋將被文檔注釋分析工具忽略,該行不會(huì )生成到文檔中。如:
//## This line will be ignored.
包含有如下標識符的注釋塊也不會(huì )被生成到文檔中去:
"Ignore Text", "$Log", "$Filename", "$Revision", "$Date", "$Author", "$History", "$Id"
用于描述該單元的用途,作者,功能。放于單元文件的最前面:
{ ##Unit Name: %UNIT% ##Initial Date: %DATE% Summary 該單元的摘要說(shuō)明。 Description 該單元的詳細說(shuō)明。 See Also 參閱 Bugs 已知問(wèn)題。 Internal 內部開(kāi)發(fā)人員參閱,不會(huì )對外。 TODO 待作事項。 Author Riceball LEE(riceball@cq118.com) Riceball LEE(riceballl@hotmail.com) Copyright Copyright(C) %YEAR% by Riceball LEE Current Version 當前版本號 History 版本歷史。}unit xxx;
{ ##Procedure: %PROCNAME% ##Date: %DAY%-%MONTHSHORTNAME%-%YEAR% Summary 該函數(屬性)的摘要說(shuō)明。 Parameters %ARGUMENTS% Returns %RESULT% Conditions 調用該方法(函數)可能需要的條件 Exceptions 該方法(函數)有可能觸發(fā)的異常。 Description 該函數(屬性)的詳細說(shuō)明。 See Also 參閱 Bugs 已知問(wèn)題。 Internal 內部開(kāi)發(fā)人員參閱,在正式發(fā)布的文檔中不會(huì )發(fā)布。 TODO 待作事項。 Author Riceball LEE(riceball@cq118.com) Riceball LEE(riceballl@hotmail.com) Copyright Copyright(C) %YEAR% by Riceball LEE Current Version 當前版本號 History 版本歷史。}function xxx;
5.
盡管大多數的代碼自動(dòng)格式化工具能夠幫你重排源程序格式,以及更新保留字和標示符的大小寫(xiě),但是這最好在使用版本控制前進(jìn)行,如果你已經(jīng)使用了版本控制,建議你不要輕易使用代碼自動(dòng)格式化工具,哪怕多一個(gè)空格,版本控制工具也會(huì )認為該行已被修改,從而給程序管理帶來(lái)不變。
6.
關(guān)于Delphi代碼標準的最新文檔,你可以在
http://dev.cq118.com/web/ 處獲得。
7.
Delphi 程序設計編碼規范 For 《Delphi Development Guide》(E)
Pascal Standards FAQ (E)
JavaDoc (E)
Doc-O-matic Document (E)
Artemis Alliance Delphi Coding Standards (E)
Borland官方Object Pascal書(shū)寫(xiě)風(fēng)格指南 (E)