|
当begin语句不是一个else子句的一部分时,相应的end语句永远缩进到与begin部分相对应的位置。
三、Object Pascal
3.1 括号
永远不要在括号与括号之间的字符中间留下空格。下面的例子示范了错误的与正确地使用括号中的空格: CallProc( Aparameter ); file://错误 CallProc(Aparameter); file://正确
永远不要在一个语句中使用不必要的括号。括号只应在源代码中需要的地方使用。以下的例子示范了错误和正确的使用: if (I = 42) then file://错误 - 多余的括号 if (I = 42) or (J = 42) then file://正确 - 需要括号
3.2 保留字和关键字
Object Pascal 保留字和关键字永远是全部小写。
3.3 过程和函数(例程)
3.3.1 命名/格式化
例程的名字永远应该以大写的字母开头并且中间错落分明以便于可读性。下面是一个不正确格式的过程名称: procedure thisisapoorlyformattedroutinename;
下面是一个合适的大小写例程名称的例子: procedure ThisIsMuchMoreReadableRoutineName;
例程的名称应该同它的内容相符。一个会导致某个行为的例程应以动词开头。例如: procedure FormatHardDrive;
一个用于设置输入参数的例程应以单词set作为前缀,例如: procedure SetUserName;
一个用来接收某个值的例程应以单词get作为前缀,例如: procedure GetUserName : string;
3.3.2 形式参数
3.3.2.1 格式化
如果有的话,相同类型的形参应合并在一个语句中: procedure Foo(Param1, Param2, Param3 : Integer; Param4 : string);
3.3.2.2 命名
所有形参的名字应是十分符合它们所代表的意义,特别是应该以传送到例程中的标志符的名称为基础。一个好的参数名称应以字符A为前缀 - 例如: procedure SomeProc(AuserName : string; AuserAge : integer);
“A”前缀按约定表示该参数的名称是与类类型中的一个属性或域的名称相对应的。
3.3.2.3 参数的排序
下面的形参的顺序重点说明了注册者调用约定调用的好处。
- 最常用的参数应放在第一位,其它的参数应按从左到右的顺序排列。 - 输入参数列表应放在输出参数列表的左边。 - 将通用的参数放在特殊参数的左边,例如: procedure SomeProc(Aplanet, AContinent, Acountry, Astate, Acity) - 排序有可能有些例外,比如事件的处理。类型为TObject的Sender参数经常放在第一位。
3.3.2.4 常量参数
当一个参数为记录型、数组类型、ShortString、或接口类型并且在例程中不被改变时,这些参数应做上常量标记。这样做会让编译器更加有效率的产生有关这些不改变的参数的代码。
而例程中另外一些非变参数也可常量来传送。尽管这样做没有产生任何效果和提高效率,这将会给调用例程的使用者提供更多的信息。
3.3.2.5 名称的冲突
当使用拥有两个名称相同的例程的两个单元时,如果你调用该例程时,在uses子句中排在后面的单元中的例程将会被调用。为了解决这种“在uses子句上的模糊”冲突,要在调用该例程时写上相关的单元的前缀,例如: sysUtile.FindClose(SR); 或 windows.FindClose(Handle);
3.4 变量
3.4.1 变量的命名和格式
变量的命名应以使用它们的目的相符
循环控制变量应采用一个单独的字符作为名字,比如 I,J,或K,也可以采用更加有意义的名字,比如 UserIndex。
逻辑变量的名字应能充分表达准确的真或假的意思。
3.4.2 局部变量
一个过程中的局部变量应遵循所有其它变量的使用和命名约定。临时变量的取名应合理。
如果必须的话,在一进入例程就应初始化局部变量。局部的AnsiString变量会自动初始化为一个空的字符串。 局部接口和派分接口类型变量将会自动初始化为nil,并且局部变数和ole变数类型变量会自动初始化为Unassigned
3.4.3 全局变量的使用
使用全局变量是不推荐的。但是,在某些时候还是必须使用,而且它们也只应在必须使用的时候才使用。在这种时候,你应努力只在一段上下文范围内使用全局变量。例如,一个全局变量只应在一个单元的implemntation部分内是全局的。如果打算在多个单元类使用全局数据,你应将它们移到一个公共的单元中然后被其它所有单元使用。
全局变量可以在var子句中直接初始化为一个值。记住,所有的全局数据会自动初始化为0,因此不要将全局变量初始化为一个“空”值比如 0、nil、’’、Unassigned、等等。这样做的一个理由是因为零-初始化的全局数据在exe文件中不会占据任何空间。零-初始化数据被存储在一个虚拟的数据段,它在应用程序启动后被分配在一段内存中。非零-初始化的全局数据在硬盘的exe文件占用空间。
3.5 类型
3.5.1 大写约定
如果类型的名字是保留字,那么它应全部小写。Win32 API类型通常全部大写,并且你必须遵循在Windows.pas或其他API单元中的详细类型名称的约定。对于其他变量名字,地一个字母应为大写,而其他字母应错落有致。下面是一些例子: var MyString : string; file://保留字 WindowHandle : HWND; file://Win32 API 类型 I : Integer; file://在System单元中引进的类型标识符
3.5.1.1 浮点指针类型
不推荐使用Real类型,因为它的存在只是为了向前兼容早期的Pascal代码。在通常情况下用Double来实现浮点指针的需要。并且,Double对处理器和总线而言是做了最优化处理的,它也是IEEE中定义的标准数据格式。只有当需要的范围超出Double所定义的范围时才使用Extended。Extended是intel定义的类型且在Java中不支持。只有当浮点指针变量的实际字节大小有其意义时才使用Single。(比如当使用另一种语言的DLLs时)。
3.5.1.2 枚举类型
枚举类型的名字需符合使用该类型的目的。该类型的名字需以字符T为前缀,以表明这是一个类型。枚举类型中的标识符列表必须包含两个或三个字符的前缀来对应于该枚举类型的名字 - 例如: TsongType = (stRock, stClassical, stCountry, stAlternative, stHeavyMetal, stRB); 一个枚举类型的实例的名字应与不要前缀的枚举类型(SongType)相同,除非有更好的原因来赋予该变量更特殊的名字,比如:FavoriteSongType1,FavoriteSongType2 等等。
3.5.1.3 变数和ole变数类型
通常不建议使用变数和Ole变数类型。但在只有运行时刻才能知道数据类型的程序中必须使用该类型,这种情形多出现在COM和数据库开发中。Ole变数使用在以COM为基础的编程中例如自动化和ActiveX控制,而变数使用在非COM的编程中,这是因为变数可以十分有效地存储本地Delphi字符串(同一个字符串变量一样),但Ole变数会将所有的字符串转换为Ole字符串(WideChar 字符串)并且并不实例运算 - 它们永远拷贝。
3.5.2 结构类型
3.5.2.1 数组类型
数组类型的名字需符合它们使用的目的。该类型的名字必须加以前缀T。如果须声明该数组类型的指针,那么该指针需加以前缀P而且应立即声明在该数组声明的前面。例如: type PCycleArray = ^TCycleArray; TCycleArray = array[1…100] of integer; 在实际应用中,数组的变量实例的名称应是其类型的名字去掉前缀T。
3.5.2.2 记录类型
记录类型的名字应符合使用它们的目的。其类型的声明应加以前缀T。如果要声明该记录类型的指针,就应加以前缀P并且应紧靠在类型声明的前面声明。例如: type PEmployee = ^TEmployee; TEmployee = record EmployeeName : string; EmployeeRate : Double; end;
3.6 语句
3.6.1 if 语句
在if/then/else语句中最常发生的行为应放在then子句中,而其它发生可能性较小的行为应放在else子句中。
尽量避免使用嵌套的if语句,在这种情形下应用多个if语句来判断各种可能。
不要使用if嵌套超过五级深度。应使代码编写得更加清晰、明了。
不要在if语句中使用不必要的圆括号。
如果在if语句中有多个条件需测试,这些条件应按计算强度由少到多的顺序从左到右排列。这样做能使编译器在编译代码时获得布尔估算逻辑的捷径,从而使你的代码获得最佳的优化。举例来说,如果条件1快过条件2,而条件2快过条件3,那么在if语句中的排列应是: if 条件1 and 条件2 and 条件3 then
3.6.2 case 语句
3.6.2.1 一般性话题
在一个case语句中的各个独立的单元应以数字或字母顺序排列。
每一个case单元的动作行为应保持简单而不应该超过四到五行代码。如果所要执行的动作过于复杂应采用独立的过程或函数。
Case语句中的else子句只有当需要缺省行为或处理错误时才使用。
3.6.2.2 格式
case语句应遵循其它结构的缩格和命名约定。
3.6.3 while 语句
在一个while语句中不建议使用exit过程来跳出循环,尽量仅使用循环条件来跳出循环。
在一个while循环中所用的初始化代码应紧靠在进入while循环前面出现而不要被其它不相关的语句隔开。
任何结束后的处理应在循环之后立即进行。
3.6.4 for 语句
for语句只有当循环次数已知的情况下才能取代while语句使用。
3.6.5 repeat 语句
repeat语句的使用同while语句一样,并且遵循同样的通用方针。
3.6.6 with 语句
3.6.6.1 一般话题
with语句应节省使用,并且带有大量的警告。避免过度使用with语句并且在with语句中小心使用多个对象、记录等等。例如: with Record1, Record2 do 这些事情会使程序员感到困惑并难以发现问题所在。
3.6.6.2 格式
with 语句遵循本文档所说明的命名约定和缩格的格式规则。
3.7 结构异常处理
3.7.1 一般话题
异常的处理大量地使用在错误纠正和资源保护方面。这就是说一旦资源被分配,一个try…finally必需加以使用来保证该资源被正确的释放。这种异常的保护也是指在一个单元的initializition/finalization或一个对象的constructor/destructor中进行资源的分配和释放。
3.7.2 try…finally的使用
任何情形下,每一次的分配都应跟随一个try…finally。举例来说,下面的代码会造成可能的错误: SomeClass1 := TsomeClass.Create; SomeClass2 ;= TsomeClass.Create; try { do some code } finally SomeClass1.Free; SomeClass2.Free; end;
一个更安全更合适的分配过程应是: SomeClass1 := TSomeClass.Create; try SomeClass2 := TsomeClass.Create; try { do some code } finally SomeClass2.Free; end; finally SomeClass1.Free; end;
3.7.3 try…except的使用
只有当在异常被触发而你想执行一些任务时才使用try…except。通常,你没有必要为了只是简单地在屏幕上显示一个错误信息而使用try…except语句,因为这会被Application对象自动执行。如果你想在except子句中执行完一些任务之后调用缺省的异常处理,使用raise来重新触发异常到下一个句柄。
3.7.4 try…except…else的使用
try…except中的else子句不建议使用,因为它会打断所有的异常包括那些你没有准备的异常。
3.8 类类型
3.8.1 命名和格式
类类型的名称应符合使用它们的目的。类型名字应加以前缀T以表明这是一个类型的定义 - 例如: type Tcustomer = class(TObject) 类型的实例通常是没有前缀T的类型的名字 - 例如: var Customer :Tcustomer; 注意:查阅“构件类型的命名标准”来获得更多有关构件命名的信息。
3.8.2 域
3.8.2.1 命名/格式
类的域名遵循与变量标识符同样的约定除了它们应以F为前缀,来表明这是一个域的名称。
3.8.2.2 可视化
所有的域都必需是私有的。想在类的范围之外存取域得通过属性来使用。
3.8.3 方法
3.8.3.1 命名/格式
方法的命名应遵循本文档中有关过程和函数的约定叙述。
3.8.3.2 使用静态的方法
如果使用一个静态的方法,那么该方法就不能被该类的后代类所继承。
3.8.3.3 使用虚拟/动态的方法
如果你打算该类的方法能被后代的类所继承就得使用虚拟的方法。只有在该方法有多个继承时(直接的或间接的)才使用动态的方法。例如,一个类类型包含一个可继承的方法,而100个后代类要继承这种方法,那么这个方法就会动态地产生为100个后代类使用的内存。
3.8.3.4 使用抽象的方法
如果在一个类中使用抽象的方法,该类就不能被创建。只有在那些永远不会被创建的类中使用抽象的方法。
3.8.3.5 属性存取方法
所有存取类的方法都只能出现在类的private或protected部分。属性存取方法的命名应遵循过程和函数的约定规则。读取存取方法(方法读取器)必需以单词Get为前缀。写入存取方法(方法写入器)必需以单词Set为前缀。方法写入器的参数的名字应为Value,并且它的类型应是它所操作的属性的类型。例如: TSomeClass = class(TObject) private FsomeField : Integer; protected function GetSomeField : Integer; procedure SetSomeField(Value : Integer); public property SomeField : Integer read GetSomeField write SetSomeField; end;
3.8.4 属性
3.8.4.1 命名/格式
属性如果是表示为一个私有域的存取器的话,那么它的名字应是它们所操作的域的名字除去解释符F。
属性的名字应是名词,不是动词。属性表示的是数据,而方法表示的 上一页 [1] [2] [3] [4] [5] [6] [7] [8] 下一页 [系统软件]InstallShield Express for delphi制作安装程序定… [常用软件]InstallShield Express制作Delphi数据库安装程序 [Delphi程序]为什么选择Delphi.Net ? [Delphi程序]《关于VisiBroker For Delphi的使用》(4) [Delphi程序]转贴:Conversion to Delphi 6: Missing unit Pro… [Delphi程序]Borland Delphi 9 的新特性 [Delphi程序]Delphi 键盘码表 [Delphi程序]Chuck Jazdzewski的离开意味着Delphi的终结吗? [Delphi程序]Delphi Access violations 问题的解决之道 [Delphi程序]QQ2000B刷屏机的源码,(Delphi,VC)双版本的
|