D
delphilai
Unregistered / Unconfirmed
GUEST, unregistred user!
DOC. NO. WholeWise -SS-02-10-12A (DELPHI软件开发编码规范.doc)
Confidential
(秘密)
宏智科技
DELPHI软件开发编码规范
Version 1.1.0
2002-10-12
作者: 曾庆顺
WholeWise
宏智科技*2002
版权所有
目 录
1 文档更新记录 1
2 前言 1
3 DELPHI代码标准规范 1
3.1 编程原则 1
3.2 项目目录结构 1
3.3 一般的源代码格式规则 2
3.3.1 缩进 2
3.3.2 边距 2
3.3.3 begin
...end 2
3.4 OBJECT PASCAL 2
3.4.1 括号 2
3.4.2 保留字和关键字 2
3.4.3 过程和函数 2
3.4.4 变量 3
3.4.5 常量 4
3.4.6 类型 5
3.4.7 构造类型 5
3.4.8 语句 6
3.4.9 结构化异常处理 7
3.4.10 类 7
3.5 文件 9
3.5.1 项目文件 9
3.5.2 窗体文件 9
3.5.3 数据模块文件 9
3.5.4 远程数据模块文件 9
3.5.5 单元文件 9
3.6 窗体与数据模块 11
3.6.1 窗体 11
3.6.2 数据模块 11
3.7 包 12
3.7.1 运行期包与设计期包 12
3.7.2 文件命名标准 12
3.8 控件 12
3.8.1 自定义控件 12
3.8.2 标准控件的命名规范 13
3.8.3 标准控件缩写标准 13
4 编码规范 13
4.1 过程及函数的编码规范 13
4.1.1 注释 13
4.1.2 变量取名及含义 14
4.1.3 书写格式 15
5 界面 15
5.1 总体要求 15
5.2 屏幕分辨率及颜色设置 15
5.3 窗口大小及操作方式 15
5.4 控件设计 15
5.5 窗口设计 16
5.5.1 字体 16
5.5.2 边框 16
5.5.3 颜色 16
5.5.4 对齐方式 16
5.5.5 页面布局 16
附页: 17
1 文档更新记录
更新内容 更新人员 日期
文档创建 曾庆顺 2002-10-12
2 前言
Delphi被人们称为“第四代编程语言”,它具有基于窗口和面象对象的方法、高速的编译、强大的数据库支持与Windows的紧密结合。基于以上特点,同时考虑到提高软件开发效率,降低软件开发过程中出现错误的可能性,并使软件系统各模块保持一致的风格,为了统一公司软件开发的设计过程中关于数据库CLIENT端开发对象设计的规范,便于交流和维护,特研究和编制本编码规范。
3 Delphi代码标准规范
3.1 编程原则
Ø 多写注释文字;
Ø 数据与界面分离;
Ø 减少资源占用;
Ø 不采用没有源代码的第三方控件;
Ø 合理的异常处理.可以处理意外情况时不要随便使用try except等;
Ø 重视每一个编译器报警.尽量消除报警。
3.2 项目目录结构
src/ 源代码目录
dcu/ 编译输出目录
comp/ 组件目录,所有组件拷贝到此处,并在此处安装
bin/ 可执行代码目录,包含运行环境
res/ 资源,图片,图标
bak/ 备份目录,至少每天一次,用zip格式,文件名=项目名+日期.zip;如email0928.zip;表示邮件9月28日备份,如果每天多次备份,则文件名中加入小时分钟信息,如email09281305.zip;表示邮件9月28日13:05分备份
doc/ 文档目录,存放项目相关文档
如果是按模块分工的开发方式,则在以上目录的上级增加一级模块名称的目录,以便将来做集成时的管理
3.3 一般的源代码格式规则
3.3.1 缩进
缩进就是每级间有两个空格。不要在源代码中放置制表符。这是因为,制表符的宽度随着不同的设置和代码管理实用程序(打印、文档及版本控制等)而不同。通过使用Tools | Emvironment 菜单,在Environment Options 对话框的G e n e r a l 页上,不要选中U s e
Tab Character 和Optimal Fill 复选框,这样,制表符就不会被保存。
3.3.2 边距
边距设置为8 0 个字符。源代码一般不会因写一个单词而超过边距,但本规则比较灵活。只要可能,长度超过一行的语句应当用逗号或运算符换行。换行后,应缩进两个字符。
3.3.3 begin
...end
b e g i n 语句必须单独占一行。例如,下面第一行是错误的,而第二行正确:
for V_Cnt:=0 to 10do
begin
// 错, begin
与f o r 在同一行
for V_Cnt:=0 to 10do
// 对, begin
在另外一行中
begin
//代码行
end ;
// End Of For V_Cnt
相应的end语句永远缩进到与begin
部分相对应的位置。
3.4 Object Pascal
3.4.1 括号
在左括号与下一字符之间必须加空格。同样,右括号与前一字符也必须加空格。下面的例子演示了正确与不正确的空格。
CallProc( Aparameter );
//正确!
CallProc( Aparameter);
//错!
不要在语句中包含多余的括号。在源代码中,括号只有在确实需要时才使用。下面的例子演示了正确与不正确用法:
if (V_Cnt=42) then
// 错,括号是多余的
if (V_Cnt=42) or (V_Num=42) then
// 正确,必须使用括号
3.4.2 保留字和关键字
Object Pascal 语言的保留字和关键字应完全的小写。
3.4.3 过程和函数
1. 命名与格式
过程和函数名应当以大写字母开始,且大小写交错以增加可读性,形式为:类型+过程/函数标识+词干。
类型: 系统公用函数或过程统一使用Pub词,其它模块使用该模块简称。
过程/函数标识: 过程为 Proc 函数为:Func
词干: 尽量使用英文单词全称,单词首字母大写,其它字母小写,首单词改量使用动词,如设置使用Set,获取使用 Get ,增加使用 Add ,删除使用Delete等。
例: Procedure SysProcFormatHardDrive;
表示系统模块的格式化硬盘过程
Function PubFuncSetUserName() 表示设置用户名称的公用函数
2. 形参
(1) 格式
只要可能,同一类型的形参应当归并在一起:
procedure Foo(const Param1,Param2,Param3:Integer;const Param4:string);
(2) 命名
所有形参的名称都应当表达出它的用途,由英文单组合而成,各单词首字母大写
procedure SomeProc(const I_UserName:string;
const I_UserAge:integer);
(3) 参数顺序
最常用的参数应当作为第一个参数,按使用频率依次从左到右排。
输入参数位于输出参数之前。
范围大的参数应当放在范围小的参数之前。例如:
SomeProc(I_APlanet,I_AContinent,I_AContinent,I_ACountry,I_AState,I_ACtity)
有些则例外。例如,在事件处理过程中,TObject 类型的Sender 参数往往是第一个要传递的参数。
(4) 常量参数
要使记录、数组、短字符串或接口类型的参数不能被例程修改,就应当把形参标以Const 。这样,编译器将以最有效的方式生成代码,保证传递的参数不可变。如果其他类型的参数希望不被例程所修改,也可以标上c o n s t 。尽管这对效率没有影响,但这给例
程的调用者带来了更多的信息。
(5) 参数引用
除需要通过参数返回值给调用者的参数外,所有参数必须指定为 const 类型,传入参数在函数内部只能作引用,不允许直接对传入的参数进行修改。
(6) 函数出口要求
所有函数只允许有一个出口,不允许在函数过程中使用return返回,如果在函数中间需要返回,统一使用goto语句跳转到出口处,返回值统一使用RESULT。
例子:
procedure SomeProc(const I_UserName:string;
const I_UserAge:integer);
(7) 名称的冲突
当使用拥有两个名称相同的例程的两个单元时,如果你调用该例程时,在uses子句中排在后面的单元中的例程将会被调用。为了解决这种“在uses子句上的模糊”冲突,要在调用该例程时写上相关的单元的前缀,例如:
sysUtile.FindClose(SR);
或
windows.FindClose(Handle);
3.4.4 变量
1. 变量的命名与格式
变量的名称应当能够表达出它的用途,采用格式如下:
变量作用域类型+“_”+名称词干,如G_FileCount 表示文件数量,全局型整型变量,名称词干为一到多个(不要太多,总长不得超过Delphi的限制且不得使用Delphi系统禁用的字母)英文单词或英文单词缩写,各英文字母的第一个字母大写。名称词干要考虑到描述对象单数复数,对复数应该在词干后面加上小写s
例:
序号 变量名称 Comments
1 G_FileName “文件名”字符串类型(全局)
2 P_FileCount “文件总数”整型(单元)
3 V_Height “高度”实型(本过程)
2. 标识符的前缀符规则
输入变量: I_变量英文准确描述;例:I_SerNo 输入变量,序列号
输出变量: O_变量英文准确描述;例:O_UserName输出变量,用户名
输入输出类型变量 IO_变量英文准确描述;例:IO_CardNo 输入输出变量,卡号
内部变量: V_变量英文准确描述;
全局变量: G_变量英文准确描述;
局部公共变量: P_变量英文准确描述;
标号(LABEL): L_英文准确描述;
结构变量: 在上述前缀符后加上R,如 VR_UsrInfo , IR_UsrInfo
类变量: 在上述前缀符后加上T,如 VC_Usr , IC_Usr
3. 局部变量
局部变量用于例程内部,在例程的begin
之前定义,以大写的“V”开头,遵循其他变量的命名规则。如果需要的话,应当在例程的入口处立即初始化变量。局部的A n s i S t r i n g 类型的变量自动被初始化为空字符串,局部的接口和d i s p i n t e r f a c e 类型的变量自动被初始化为n i l ,局部的Va r i a n t 和O l e Va r i a n t 类型的变量自动被初始化为U n a s s i g n e d .
4. 窗体变量
作用域只在本窗体或本单元中使用,在窗体的private内定义,以大写的“P”开头,遵守变量的命名规则。在窗体的OnCreate事件中初始化。
5. 全局变量
不推荐使用全局变量。但是,在某些时候必须使用时,应努力只在一段上下文范围内使用全局变量。例如,一个全局变量只应在一个单元的implemntation部分内是全局的。如果打算在多个单元类使用全局数据,应将它们移到一个公共的单元中然后被其它所有单元使用。
全局变量可以在var子句中直接初始化为一个值。所有的全局数据会自动初始化为0,因此不要将全局变量初始化为一个“空”值比如 0、nil、’’、Unassigned、等等。这样做的一个理由是因为零-初始化的全局数据在exe文件中不会占据任何空间。零-初始化数据被存储在一个虚拟的数据段,它在应用程序启动后被分配在一段内存中。非零-初始化的全局数据在硬盘的exe文件占用空间。
全局变量以大写 “G”开头。
3.4.5 常量
在Delphi中常量的定义有两种方式Const方式和Resourcestring方式,前者是常量命名的一般方式,后者定义的字符串常量被存储在程序的资源中的一个字符串表格中。不论用哪种方式定义常量,常量的命名必须以常量作用范围前缀(G、P、V分别代表常量作用范围为全局、单元、本过程)其后紧接与意义相关联的名称词干。名称词干为一到多个(不要太多,总长不得超过Delphi的限制且不得使用Delphi系统禁用的字母)英文单词或英文单词缩写,各英文字母全部大写。名称词干要考虑到描述对象单数复数,对复数应该在词干后面加上大写S 。例如:
序号 常量名称 Comments
1 P_CIRCELNUMBER 循环次数(单元)
2 G_SERVERNAME 服务器名(全局)
3.4.6 类型
1. 大小写规则
类型标识符是保留字,应当全部小写。Win32 API 类型常常全部大写,并且遵循诸如Windows.pas或其他A P I 单元中关于特定类型名的规则。对于其他变量名,第一个字母应大写,其他字母则大小写交错。下面是一些例子:
v a r
lM y S t r i n g : s t r i n g ;
// 保留字
lWi n d o w s H a n d l e : H W N D ;
/ / Win32 API 类型
I : I n t e g e r ;
/ /在S y s t e m 单元中引入的类型标识
2. 浮点型
不使用R e a l 类型,通常情况下,对于浮点数应当使用D o u b l e 。当需要比D o u b l e 提供的范围更大时,可以使用E x t e n d 。
3. 枚举型
枚举类型名必须代表枚举的用途。名称前要加T 字符作为前缀,表示这是个数据类型。枚举类型的标识符列表的前缀应包含2 ~ 3 个小写字符,来彼此关联。例如:
TSongType=(stRock,stClassical,stCountry,stAlternative,stHeavyMetal,stRB);
枚举类型的变量实例的名称与类型相同,但没有前缀T ,也可以给变量一个更加特殊名称,诸如
F a v o r i t e S o n g Ty p e l 、F a v o r i t e S o n g Ty p e 2 等等。
4. Va r i a n t 和O l e Va r i a n t
一般不建议使用Va r i a n t 和O l e Va r i a n t 。但是,当数据类型只有在运行期才知道时(常常是在C O M 和数据库应用的程序中),这两个类型对编程就有必要。当进行诸如自动化A c t i v e X 控件的C O M 编程时,应当使用O l e Va r i a n t ;而对于非C O M 编程,则应当使用Va r i a n t 。这是因为,Va r i a n t 能够有效地保存
D e l p h i 的原生字符串,而O l e Va r i a n t 则将所有字符串转换为O L E 字符串(即Wi d e C h a r 字符串),且没有引用计数功能。
3.4.7 构造类型
1. 数组类型
数组类型名应表达出该数组的用途。类型名必须由该类型的作用域范围加上字母T 为前缀。如果要声明一个指向数组类型的指针,则必须加字母P 为前缀,且声明在类型声明之前。例如:
type
V_PCycleArray = ^TCycleArray;
V_TCycleArray = array[1…100] of integer;
end;
2. 记录类型
记录类型名应表达出记录的用途。类型名必须必须由该类型的作用域范围加上字母T 为前缀。如果要声明一个指向记录类型的指计,则必须加字母P 为前缀,且其声明在类型声明之前。例如:
type
V_PEmployee = ^TEmployee;
V_TEmployee = record
V_EmployeeName : string;
V_EmployeeRate :do
uble;
end;
3.4.8 语句
1. If 语句
在i f / t h e n / e l s e 语句中,最有可能执行的情况应放在t h e n 子句中,不太可能的情况放在e l s e 子句中。为了避免出现许多i f 语句,可以使用c a s e 语句代替。如果多于5 级,不要使用i f 语句。请改用更清楚的方法。不要在i f 语句中使用多余的括号。如果在i f 语句中有多个条件要测试,应按照计算的复杂程度从右向左排。这样,可以使代码充分利用编译器的短路估算逻辑。例如,如果C o n d i t i o n 1 比C o n d i t i o n 2 快,C o n d i t i o n 2 比C o n d i t i o n 3 快,则i f语句应这样构造:
if Conditior1 and Condition2 and Condition3 then
2. case 语句
(1) 概述
c a s e 语句中每种情况的常量应当按数字或字母的顺序排列。
每种情况的动作语句应当简短且通常不超过4 ~ 5 行代码。如果动作太复杂,应将代码单独放在一个过程或函数中。C a s e 语句的e l s e 子句只用于默认情况或错误检测。
(2) 格式
c a s e 语句遵循一般的缩进和命名规则。
3. while 语句
尽量不使用E x i t 过程来退出w h i l e 循环。如果需要的话,应当使用循环条件退出循环。所有对w h i l e 循环进行初始化的代码应当位于w h i l e 入口前,且不要被无关的语句隔开。任何业务的辅助工作都应在循环后立即进行。
4. for 语句
如果循环次数是确定的,应当用f o r 语句代替w h i l e 语句。
5. repeat 语句
不允许使用repeat语句,统一使用while或for语句。
6. with 语句
(1) 概述
一个w i t h 语句只允许对单个对象或记录进行赋值时使用。例如:
with Record1,do
(2) 格式
w i t h 语句也遵循本章关于命名和缩进的规则。
3.4.9 结构化异常处理
1.概述
异常处理主要用于纠正错误和保护资源。这意味着,凡是分配资源的地方,都必须使用t r y. . . f i n a l l y来保证资源得到释放。不过,如果是在单元的初始/结束部分或者对象的构造器/析构器中来分配/释放资源则例外。
2. try. . . f i n a l l y 的用法
任何情形下,每一次的分配都应跟随一个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. try. . . e x c e p t 的用法
如果你希望在发生异常时执行一些任务,可以使用t r y. . . e x c e p t 。通常,没有必要为了简单地显示一个错误信息而使用t r y. . . e x c e p t ,因为A p p l i c a t i o n 对象能够自动根据上下文做到这一点。如果要在子句中激活默认的异常处理,可以再次触发异常。
4. try. . . e x c e p t . . . e l s e 的用法
不鼓励使用带e l s e 子句的t r y. . . e x c e p t ,因为这将阻塞所有的异常,包括你没有准备处理的异常。
3.4.10 类
1. 命名与格式
类的名称应当表达出类的用途。类名前要加字母T ,表示它是一个类型。例如:
t y p e
T C u s t o m e r = c l a s s ( TO b j e c t ) ;
类的实例名称与类名相同,只不过没有前缀T 。
v a r
C u s t o m e r : T C u s t o m e r ;
注意关于控件的命名,请参阅3.8 节“控件”。
2. 字段
(1) 命名与格式
字段的命名遵循与变量相同的规则,只不过要加前缀F ,表示这是字段。
(2) 可见性
所有字段必须为私有。如果要在类的作用域之外访问字段,可借助于类的属性来实现。
3. 方法
(1) 命名与格式
方法的命名遵循与过程和函数相同的规则。
(2) 静态方法
当你不希望一个方法被派生类覆盖时,应当使用静态方法。
(3) 虚拟方法与动态方法
当你希望一个方法能被派生类覆盖,应当使用虚拟方法。如果类的方法要被多个派生类直接或间接地使用,则应当用动态方法。例如,某一个类含有一个被频繁覆盖的方法,并有1 0 0 个派生类,则应将方法定义为动态的,这样可以减少内存的开销。
(4) 抽象方法
如果一个类要创建实例,则不要使用抽象方法。抽象方法只能在那些从不创建实例的基类中使用。
(5) 属性访问方法
所有属性访问方法应当定义在类的私有或保护部分。
属性访问方法遵循与过程和函数相同的规则。用于读的方法应当加G e t 前缀,用于写的方法应当加S e t 前缀,并且有一个叫Va l u e 的参数,其类型与属性的类型相同。例如:
TSomeClass = class(TObject)
private
FsomeField : Integer;
protected
function GetSomeField : Integer;
procedure SetSomeField(Value : Integer);
public
property SomeField : Integer read GetSomeField write SetSomeField;
end;
4. 属性
属性作为私有字段的访问器,遵循与字段相同的命名规则,只不过没有F 前缀。属性名应为名词,而不是动词。属性是数据,而方法是动作。数组属性名应当是复数,而一般的属性应当是单数。
5. 访问方法的使用
尽管不是必须,但还是建议你使用写访问方法来访问代表私有字段属性。
3.5 文件
3.5.1 项目文件
项目文件的名称应当具有描述意义,且以prj开头。例如,“The Delphi 5 Developer’s Guide Bug Manager ”的项目名称为PrjDDUBugs.dpr ,一个系统信息程序的名称为PrjSysInfo.dpr 。
3.5.2 窗体文件
窗体的命名必须以Frm(Form缩写)开头,其后紧接与意义相关联的名称词干。名称词干为一到多个(不要太多,总长不得超过Delphi的限制且不得使用Delphi系统禁用的字母)英文单词或英文单词缩写,各英文字母的第一个字母大写。名称词干要考虑到描述对象单数复数,对复数应该在词干后面加上小写s 。例如:
序号 窗口名称 说明
1 FrmAbout 关于本系统的版权信息
2 FrmSystemError 系统出错提示
3 FrmMain 系统主界面
4 FrmReportSheet 报表输出
3.5.3 数据模块文件
数据模块文件的名称应当表达出数据模块的作用,且以Dm开头。例如,Customers 数据模块的文件名叫DmCustomers.dfm。
3.5.4 远程数据模块文件
远程数据模块文件的名称应当表达出远程数据模块的用途,且以Rdm开头。例如: 自定义远端数据模板的文件名字应为RdmCustomers.dfm
3.5.5 单元文件
1.普通单元文件
窗体单元名,以“U”开头,再加上相应的窗体名。名称词干为一到多个(不要太多,总长不得超过Delphi的限制且不得使用Delphi系统禁用的字母)英文单词或英文单词缩写,各英文字母的第一个字母大写。名称词干要考虑到描述对象单数复数,对复数应该在词干后面加上小写s 。例如:
序号 单元名称 说明
1 UPublicVal 公用变量统一定义单元
2 UPublicFunction 公用函数统一定义单元
3 UFrmMain 主单元
4 UFrmAbout About窗口单元
单元文件应当按照以下的顺序包含下列元素:
版权/标识块注释
单元名
接口段
实现部分
一个结束符”end.
”
每个部分之间至少空一行。
其它的元素应当被结构化成你认为最适当的顺序。但文件注释应当出现在文件的最开始,然后是单元名,然后是任何条件定义、编译器指示符或包含语句,然后是uses字句:
//单元功能,创建人,创建日期,最近修改人,最后修改时间以及版本说明
unit UComObjectTest;
//interface部份只包含需要被外部单元访问的类型、变量、过程与函数的声明。而且,
//这些声明应当在I m p l e m e n t a t i o n 部分之前。
interface
//只包含该部分需要的单元。不要包含可能由D e l p h i 自动添加的单元
uses
ComObj, ActiveX, Project1_TLB, StdVcl;
type
TmyCom = class(TAutoObject, ImyCom)
protected
{ Protected declarations }
function Get_EditText:widestring;safecall;
end;
//包括本单元私有的类型、变量、过程与函数的实现。
implementation
//应当只包含该部分需要的单元,不要有多余的单元。
uses ComServ,SysUntils,unit1,ExtCtrls,Dialogs,typinfo;
{ TmyCom }
function TmyCom.Get_EditText: widestring;
begin
end;
end.
2. 窗体单元
窗体单元文件的名称在相应的窗体名称前加上U。例如,A b o u t 窗体的单元名称叫FrmAbout.dfm,主窗体的单元文件名称叫UFrmAbout.pas。
3. 数据模块单元
数据模块单元文件的名称与相应的数据模块名称相同。例如,一个自定义数据模板单元的名称应为DmCustomers.pas。
4. 通用的单元
一般目的单元的取名应符合使用该单元的目的。例如,一个包含全局变量的单元取名为UCustomerGlobals.pas。
注意,该单元的名字不能与它的工程中所使用的所有包中的单元的名字相同。不赞成使用一般的或通用的单元名字。5. 控件单元
控件单元应放在单独的路径中,以表明它们是定义控件的单元。它们一般与项目不放在同一路径下。单元文件名称应表达出其内容。
3.6 窗体与数据模块
3.6.1 窗体
1. 窗体类型的命名标准
窗体类型的名称应当表达出窗体的用途,且要加T 前缀,后跟Frm和描述性名。例如,
A b o u t窗体类型名称为:
TAboutFrom = class(TForm);
主窗体的类型名称为:
TMainForm = class(TForm);
客户登录窗体的类型名称为:
TCustomerEntryForm = class(TForm);
2. 窗体实例的命名标准
窗体实例的名称与相应的类型名称相同,但没有前缀T 。例如,前面提到的窗体类型与实例的名称为:
类型名 实例名
TFrmAbout FrmAbout
TFrmMain FrmMain
TFrmFormCustomerEntry FrmFormCustomerEntry
3. 自动创建的窗体
除非特别原因,只有主窗体才自动生成。其他所有窗体必须从Project Options 对话框的自动生成列表中删除。
4. 模式窗体实例化函数
所有窗体单元都应当含有实例化函数,用于创建、设置、模式显示和释放窗体。这个函数将返回由窗体返回的模式结果。传递给这个函数的参数遵循参数传递的规则。之所以要这样封装,是为了便于代码的重用和维护。窗体的变量应当从单元中移走,改在窗体实例化函数中作为局部变量定义(注意,要求从P r o j e c tO p t i o n s 对话框的自动生成列表中移走该窗体。请看前面的内容)。
3.6.2 数据模块
1. 数据模块的命名标准
数据模块类型名称应表达出它的用途,且要加前缀T ,后跟描述性名称,最后是DataModule 。
例如,一个自定义的数据模板有时候应该象:
TCustomerDataModule = class(TDataModule)
一个命令式的数据模板的名字应象:
TOrdersDataModule = class(TDataModule)
2. 数据模块实例的命名标准
数据模块实例的名称应当与相应的类型名称相同,但没有前缀T 。例如,前面的数据模块类型、实例名称如下:
类型名称 实例名称
TCustomerDataModule CustomerDataModule
TOrdersDataModule OrdersDataModule
3.7 包
3.7.1 运行期包与设计期包
运行期包中应当只包含所需要的单元。那些属性编辑器和控件编辑器的单元应当放在设计期包中。注册单元也应当放在设计期包中。
3.7.2 文件命名标准
包的命名遵循下列模式:
FhdLibXxxvv.pkg — 设计期包
FhdStdXxxvv.pkg — 运行期包
其中,Fhd 代表一个3 字符的前缀,用于标识公司。v v 代表包的版本号,其中也包含了Delphi 的版本号。注意包名称中的lib 或std 分别表示这是设计期包还是运行期包,Xxx表示包的内容。例如:
FhdStdAdo50.pkg — 设计期包
FhdLibAdo50.pkg — 运行期包
3.8 控件
3.8.1 自定义控件
1. 控件类型的命名标准
控件的命名与类的命名类似,只不过它有3 个字符的前缀。这些前缀用以标识公司、个人或其他实体。公司统一为 : Fhd。
2. 控件单元
控件单元只能含有一个主要控件,这是指出现在控件选项板上的控件。其他辅助性的控件或对象也可以包含在同一单元中。
3. 注册单元
控件的注册过程应当从控件单元中移走,放在一个单独的单元中。这个注册单元用于注册所有控件、属性编辑器、控件编辑器、向导等。控件注册应当在设计期包中进行。因此,注册单元应当包含在设计期包而不是运行期包中。建议注册单元这样命名:
F h d R e g . p a s
其中,Fhd 为3 个字符前缀,以标识公司。
3.8.2 标准控件的命名规范
控件的命名必须以控件类型的英文缩写开头,其后紧接与意义相关联的名称词干。名称词干为一到多个(不要太多,总长不得超过Delphi的限制且不得使用Delphi系统禁用的字母)英文单词或英文单词缩写,各英文字母的第一个字母大写。名称词干要考虑到描述对象单数复数,对复数应该在词干后面加上小写s
例:
序号 控件名称 控件缩写 控件命名范例
1 TButton Btn BtnOk
2 TPictureButton Pcb PcbThankInfo
3 TCheckBox Chb ChbAgeShow
3.8.3 标准控件缩写标准
见附页
4 编码规范
在编码过程中,应该遵守如下规则:
· 多写注释文字.
· 数据与界面分离.
· 减少资源占用.
· 不采用没有源代码的第三方控件.
· 合理的异常处理.可以处理意外情况时不要随便使用try except等
· 重视每一个编译器报警.尽量消除报警.
除了以上所提到的基本要求外, 具体项目由项目负责人决定更细致更严格的要求.
代码书写规范
· 源程序每个文件控制在1000~2000行
· 每个函数行数限制在200行之内
· Delphi 2格缩进
· 函数要有说明,至少一行
· 每个接口(全局)函数的入口出口参数要加注释
· 每条语句必须在Delphi规定的打印线内
4.1 过程及函数的编码规范
4.1.1 注释
1.位置要求:
1)注释行的长度以在最大化窗口内可以看到全部内容为宜,如果一行不够显示需要换行,下一行注释语句与上一行注释语句应对齐。
2)变量申明的注释放在变量申明语句的后面,并以 // 为注释语句
3)注释行一律放在被注释语句的上一行。
4)注释行中,注释命令与注释内容空一个空格,如:
var
V_BpMode:String;
// 用户服务类型
2. 在函数、过程、模块、单元、类的开始处严格按如下格式写出注释:
// 过程(或函数)名:
// 功能描述:
// 参数说明:
// 返回值:
// 时间:
// 修改者:
// 修改时间:
// 该调用其它模块说明
// 调用该模块的其它模块说明
3.逻辑上多重嵌套的情况,如try …. Finnaly;
if …. then
…;
begin
d end;
while语句 ;for 语句等,需要加配对注释
例:
如果出现多重嵌套语句,如多重if , while , try , for 等,应加上配对注视
多重if 注视要求:
if 条件1 then
begin
if 条件2 then
begin
end ;
// end of if 条件2
end ;
// end of if 条件1
多重while , for 注视要求同 if 语句
多重try 注视要求:
try{ // try1
try{ // try2
try{ //try3
}finally // end of try3
}finally // end of try2
}finary // end of try1
4. 请在各程序段加上程序思路说明。
4.1.2 变量取名及含义
变量取名请遵守命名规范,对使用频繁、关键变量,为了便于阅读和修改,在定义时必须加上注释标明其含义。
4.1.3 书写格式
1. 用分层缩进的写法显示嵌套结构的层次;
2. 在注释段与程序段、以及不同程序段插入空行;
3. 每行只写一条语句。
5 界面
5.1 总体要求
系统界面风格采用与Windows操作系统一致。
5.2 屏幕分辨率及颜色设置
程序设计、开发时采用800*600分辨率,16位增强色,小字体;
在同一窗口中除黑、白、深灰、灰色外,最多使用四种彩色:
l 红色用于表示危险、停止或红头文件头;
l 黄色表示注意;
l 绿色表示安全,可以执行;
l 蓝色表示确定。
5.3 窗口大小及操作方式
主控窗口大小按满屏设计,在系统实际运行时可根据客户端的分辨率及任务栏设置(自动隐藏或不自动隐藏)自动进行控件的位置、间距的调整。
其它窗口(如系统载入窗、用户登录窗、信息提示窗等)则根据实际需要设计,在兼顾系统实际运行时客户端分辨率及任务栏设置的前提下,尽量固定其大小。
使用菜单与工具条相结合、鼠标与键盘操作相结合的方式;菜单项及工具条按钮均应在主控窗口的状态提示区提供信息提示功能并设置快捷键,保证用户在脱离鼠标的情况下也可通过键盘来操作。
5.4 控件设计
工具条按钮尽量采用Windows常用按钮,如在下表中已存在的按钮,则系统中应采用
说明 按钮样式 说明 按钮样式
新建(Ctrl+N) 复制(Ctrl+C)
打开(Ctrl+O) 剪切(Ctrl+X)
删除 粘贴(Ctrl+V)
邮件 帮助主题
历史记录 在线帮助
预览 撤消操作
打印 重复操作
记录控制条 选择
查找(Ctrl+F) 继续查找
复制记录 信息显示
粘贴记录 向上
撤消记录 向下
记数 保存当前
结构 保存全部
升序排列 降序排序
5.5 窗口设计
5.5.1 字体
Ø 窗口中非标题对象字体一般采用宋体9号字;
Ø 标题字体采用宋体14号粗体字。
5.5.2 边框
Ø 窗体中的Label对象为无边框;
Ø 编辑框、选择框、检查框、列表框统一为三维下凹单线边核边框;
Ø 按钮为三维上凸单边框。
5.5.3 颜色
Ø 标签对象(Label)的颜色为黑色透明;
Ø 编辑框、选择框、检查框、列表框字体颜色为:黑色白底,全部选择时的颜色为白色兰底,不可编辑时的颜色为,灰色白底。
5.5.4 对齐方式
Ø 所有窗体中的对象尽量采用右对齐的方式
Ø Form的Scaled属性一律设为False.
Ø 采用先从左到右,再从上到下的次序。
5.5.5 页面布局
Ø 尽可能少用滚动条,当页面内容较多时尽可能使用Page Control的方式进行布局;
Ø 使用CheckBox和RadioButton时,对于同一类别的选择应使用GroupBox将它们分类。
附页:
标准控件前缀命名
Standard页
前缀 构件
mm TMainMenu
pm TPopupMenu
mmi TMainMenuItem
pmi TPopupMenuItem
前缀 构件
lbl TLabel
edt TEdit
mem TMemo
btn TButton
cb TCheckBox
rb TRadioBox
lb TListBox
cmb TComboBox
scb TScrollBar
gb TGroupBox
rg TRadioGroup
pnl TPanel
cl TCommandList
Additional页
bbtn TBitBtn
sb TSpeedButton
me TMaskEdit
sg TStringGrid
dg TDrawGrid
img TImage
shp TShape
bvl TBevel
sbx TScrollBox
clb TCheckListbox
spl TSplitter
stx TStaticText
cht TChart
Win32页
tbc TTabControl
pgc TPageControl
il TImageList
re TRichEdit
thr TTrackBar
prb TProgressBar
ud TUpDown
hk THotKey
ani TAnimate
dtp TDateTimePicker
tv TTreeView
lv TListView
hdr THeaderControl
stb TStatusBar
tlb TToolBar
clb TCoolBar
System页
tm TTimer
pb TPaintBox
mp TMediaPlayer
olec TOleContainer
ddcc TDDEClientItem
ddci TDDEClientItem
ddsc TDDEServerConv
ddsi TDDEServerItem
Internet页
csk TClientSocket
ssk TServerSocket
wbd TWebDispatcher
pp TPageProducer
tp TQueryTableProducer
dstp TDataSetTableProducer
nmdt TNMDayTime
nec TNMEcho
nf TNMFinger
nftp TNMFtp
nhttp TNMHttp
nMsg TNMMsg
nmsg TNMMSGServ
nntp TNMNNTP
npop TNMPop3
nuup TNMUUProcessor
smtp TNMSMTP
nst TNMStrm
nsts TNMStrmServ
ntm TNMTime
nudp TNMUdp
psk TPowerSock
ngs TNMGeneralServer
html THtml
url TNMUrl
sml TSimpleMail
Data Access页
ds TDataSource
tbl TTable
qry TQuery
sp TStoredProc
db TDataBase
ssn TSession
bm TBatchMove
usql TUpdateSQL
Data Controls页
dbg TDBGrid
dbn TDBNavigator
dbt TDBText
dbe TDBEdit
dbm TDBMemo
dbi TDBImage
dblb TDBListBox
dbcb TDBComboBox
dbch TDBCheckBox
dbrg TDBRadioGroup
dbll TDBLookupListBox
dblc TDBLookupComboBox
dbre TDBRichEdit
dbcg TDBCtrlGrid
dbch TDBChart
Decision Cube页
dcb TDecisionCube
dcq TDecisionQuery
dcs TDecisionSource
dcp TDecisionPivot
dcg TDecisionGrid
dcgr TDecisionGraph
QReport页
qr TQuickReport
qrsd TQRSubDetail
qrb TQRBand
qrcb TQRChildBand
qrg TQRGroup
qrl TQRLabel
qrt TQRText
qre TQRExpr
qrs TQRSysData
qrm TQRMemo
qrrt TQRRichText
qrdr TQRDBRichText
qrsh TQRShape
qri TQRImage
qrdi TQRDBMImage
qrcr TQRCompositeReport
qrp TQRPreview
qrch TQRChart
Dialogs页
对话框构件是由构件封装的真正的窗体,因此,它们应遵循窗体的命名约定。类型已由构件的名称定义。它的实例的名称是Delphi自动生成的类型实例名字去掉数字后缀。举例如下:
TOpenDialog OpenDialog
TSaveDialog SaveDialog
TOpenPictureDialog OpenPictureDialog
TSavePictureDialog SavePictureDialog
TFontDialog FontDialog
TColorDialog ColorDialog
TPrintSetupDialog PrintSetupDialog
TFindDialog FindDialog
TReplaceDialog ReplaceDialog
Win3.1页
dbll TDBLookupList
dblc TDBLookupCombo
ts TTabSet
ol TOutline
tnb TTabbedNoteBook
nb TNoteBook
hdr THeader
flb TFileListBox
dlb TDirectoryListBox
dcb TDriveComboBox
fcb TFliterComboBox
Samples页
gg TGauge
cg TColorGrid
spb TSpinEdit
spe TSpinEdit
dol TDirectoryOutline
cal TCalendar
ibea TIBEventAlerter
ActiveX页
cfx TChartFX
vsp TVSSpell
f1b TF1Book
vtc TVTChart
grp TGraph
Midas页
prv TProvider
cds TClientDataSet
qcds TQueryClientDataSet
dcom TDCOMConnection
olee TOleEnterpriseConnection
sck TSocketConnection
rms TRemoteServer
mid TMidasConnection
Confidential
(秘密)
宏智科技
DELPHI软件开发编码规范
Version 1.1.0
2002-10-12
作者: 曾庆顺
WholeWise
宏智科技*2002
版权所有
目 录
1 文档更新记录 1
2 前言 1
3 DELPHI代码标准规范 1
3.1 编程原则 1
3.2 项目目录结构 1
3.3 一般的源代码格式规则 2
3.3.1 缩进 2
3.3.2 边距 2
3.3.3 begin
...end 2
3.4 OBJECT PASCAL 2
3.4.1 括号 2
3.4.2 保留字和关键字 2
3.4.3 过程和函数 2
3.4.4 变量 3
3.4.5 常量 4
3.4.6 类型 5
3.4.7 构造类型 5
3.4.8 语句 6
3.4.9 结构化异常处理 7
3.4.10 类 7
3.5 文件 9
3.5.1 项目文件 9
3.5.2 窗体文件 9
3.5.3 数据模块文件 9
3.5.4 远程数据模块文件 9
3.5.5 单元文件 9
3.6 窗体与数据模块 11
3.6.1 窗体 11
3.6.2 数据模块 11
3.7 包 12
3.7.1 运行期包与设计期包 12
3.7.2 文件命名标准 12
3.8 控件 12
3.8.1 自定义控件 12
3.8.2 标准控件的命名规范 13
3.8.3 标准控件缩写标准 13
4 编码规范 13
4.1 过程及函数的编码规范 13
4.1.1 注释 13
4.1.2 变量取名及含义 14
4.1.3 书写格式 15
5 界面 15
5.1 总体要求 15
5.2 屏幕分辨率及颜色设置 15
5.3 窗口大小及操作方式 15
5.4 控件设计 15
5.5 窗口设计 16
5.5.1 字体 16
5.5.2 边框 16
5.5.3 颜色 16
5.5.4 对齐方式 16
5.5.5 页面布局 16
附页: 17
1 文档更新记录
更新内容 更新人员 日期
文档创建 曾庆顺 2002-10-12
2 前言
Delphi被人们称为“第四代编程语言”,它具有基于窗口和面象对象的方法、高速的编译、强大的数据库支持与Windows的紧密结合。基于以上特点,同时考虑到提高软件开发效率,降低软件开发过程中出现错误的可能性,并使软件系统各模块保持一致的风格,为了统一公司软件开发的设计过程中关于数据库CLIENT端开发对象设计的规范,便于交流和维护,特研究和编制本编码规范。
3 Delphi代码标准规范
3.1 编程原则
Ø 多写注释文字;
Ø 数据与界面分离;
Ø 减少资源占用;
Ø 不采用没有源代码的第三方控件;
Ø 合理的异常处理.可以处理意外情况时不要随便使用try except等;
Ø 重视每一个编译器报警.尽量消除报警。
3.2 项目目录结构
src/ 源代码目录
dcu/ 编译输出目录
comp/ 组件目录,所有组件拷贝到此处,并在此处安装
bin/ 可执行代码目录,包含运行环境
res/ 资源,图片,图标
bak/ 备份目录,至少每天一次,用zip格式,文件名=项目名+日期.zip;如email0928.zip;表示邮件9月28日备份,如果每天多次备份,则文件名中加入小时分钟信息,如email09281305.zip;表示邮件9月28日13:05分备份
doc/ 文档目录,存放项目相关文档
如果是按模块分工的开发方式,则在以上目录的上级增加一级模块名称的目录,以便将来做集成时的管理
3.3 一般的源代码格式规则
3.3.1 缩进
缩进就是每级间有两个空格。不要在源代码中放置制表符。这是因为,制表符的宽度随着不同的设置和代码管理实用程序(打印、文档及版本控制等)而不同。通过使用Tools | Emvironment 菜单,在Environment Options 对话框的G e n e r a l 页上,不要选中U s e
Tab Character 和Optimal Fill 复选框,这样,制表符就不会被保存。
3.3.2 边距
边距设置为8 0 个字符。源代码一般不会因写一个单词而超过边距,但本规则比较灵活。只要可能,长度超过一行的语句应当用逗号或运算符换行。换行后,应缩进两个字符。
3.3.3 begin
...end
b e g i n 语句必须单独占一行。例如,下面第一行是错误的,而第二行正确:
for V_Cnt:=0 to 10do
begin
// 错, begin
与f o r 在同一行
for V_Cnt:=0 to 10do
// 对, begin
在另外一行中
begin
//代码行
end ;
// End Of For V_Cnt
相应的end语句永远缩进到与begin
部分相对应的位置。
3.4 Object Pascal
3.4.1 括号
在左括号与下一字符之间必须加空格。同样,右括号与前一字符也必须加空格。下面的例子演示了正确与不正确的空格。
CallProc( Aparameter );
//正确!
CallProc( Aparameter);
//错!
不要在语句中包含多余的括号。在源代码中,括号只有在确实需要时才使用。下面的例子演示了正确与不正确用法:
if (V_Cnt=42) then
// 错,括号是多余的
if (V_Cnt=42) or (V_Num=42) then
// 正确,必须使用括号
3.4.2 保留字和关键字
Object Pascal 语言的保留字和关键字应完全的小写。
3.4.3 过程和函数
1. 命名与格式
过程和函数名应当以大写字母开始,且大小写交错以增加可读性,形式为:类型+过程/函数标识+词干。
类型: 系统公用函数或过程统一使用Pub词,其它模块使用该模块简称。
过程/函数标识: 过程为 Proc 函数为:Func
词干: 尽量使用英文单词全称,单词首字母大写,其它字母小写,首单词改量使用动词,如设置使用Set,获取使用 Get ,增加使用 Add ,删除使用Delete等。
例: Procedure SysProcFormatHardDrive;
表示系统模块的格式化硬盘过程
Function PubFuncSetUserName() 表示设置用户名称的公用函数
2. 形参
(1) 格式
只要可能,同一类型的形参应当归并在一起:
procedure Foo(const Param1,Param2,Param3:Integer;const Param4:string);
(2) 命名
所有形参的名称都应当表达出它的用途,由英文单组合而成,各单词首字母大写
procedure SomeProc(const I_UserName:string;
const I_UserAge:integer);
(3) 参数顺序
最常用的参数应当作为第一个参数,按使用频率依次从左到右排。
输入参数位于输出参数之前。
范围大的参数应当放在范围小的参数之前。例如:
SomeProc(I_APlanet,I_AContinent,I_AContinent,I_ACountry,I_AState,I_ACtity)
有些则例外。例如,在事件处理过程中,TObject 类型的Sender 参数往往是第一个要传递的参数。
(4) 常量参数
要使记录、数组、短字符串或接口类型的参数不能被例程修改,就应当把形参标以Const 。这样,编译器将以最有效的方式生成代码,保证传递的参数不可变。如果其他类型的参数希望不被例程所修改,也可以标上c o n s t 。尽管这对效率没有影响,但这给例
程的调用者带来了更多的信息。
(5) 参数引用
除需要通过参数返回值给调用者的参数外,所有参数必须指定为 const 类型,传入参数在函数内部只能作引用,不允许直接对传入的参数进行修改。
(6) 函数出口要求
所有函数只允许有一个出口,不允许在函数过程中使用return返回,如果在函数中间需要返回,统一使用goto语句跳转到出口处,返回值统一使用RESULT。
例子:
procedure SomeProc(const I_UserName:string;
const I_UserAge:integer);
(7) 名称的冲突
当使用拥有两个名称相同的例程的两个单元时,如果你调用该例程时,在uses子句中排在后面的单元中的例程将会被调用。为了解决这种“在uses子句上的模糊”冲突,要在调用该例程时写上相关的单元的前缀,例如:
sysUtile.FindClose(SR);
或
windows.FindClose(Handle);
3.4.4 变量
1. 变量的命名与格式
变量的名称应当能够表达出它的用途,采用格式如下:
变量作用域类型+“_”+名称词干,如G_FileCount 表示文件数量,全局型整型变量,名称词干为一到多个(不要太多,总长不得超过Delphi的限制且不得使用Delphi系统禁用的字母)英文单词或英文单词缩写,各英文字母的第一个字母大写。名称词干要考虑到描述对象单数复数,对复数应该在词干后面加上小写s
例:
序号 变量名称 Comments
1 G_FileName “文件名”字符串类型(全局)
2 P_FileCount “文件总数”整型(单元)
3 V_Height “高度”实型(本过程)
2. 标识符的前缀符规则
输入变量: I_变量英文准确描述;例:I_SerNo 输入变量,序列号
输出变量: O_变量英文准确描述;例:O_UserName输出变量,用户名
输入输出类型变量 IO_变量英文准确描述;例:IO_CardNo 输入输出变量,卡号
内部变量: V_变量英文准确描述;
全局变量: G_变量英文准确描述;
局部公共变量: P_变量英文准确描述;
标号(LABEL): L_英文准确描述;
结构变量: 在上述前缀符后加上R,如 VR_UsrInfo , IR_UsrInfo
类变量: 在上述前缀符后加上T,如 VC_Usr , IC_Usr
3. 局部变量
局部变量用于例程内部,在例程的begin
之前定义,以大写的“V”开头,遵循其他变量的命名规则。如果需要的话,应当在例程的入口处立即初始化变量。局部的A n s i S t r i n g 类型的变量自动被初始化为空字符串,局部的接口和d i s p i n t e r f a c e 类型的变量自动被初始化为n i l ,局部的Va r i a n t 和O l e Va r i a n t 类型的变量自动被初始化为U n a s s i g n e d .
4. 窗体变量
作用域只在本窗体或本单元中使用,在窗体的private内定义,以大写的“P”开头,遵守变量的命名规则。在窗体的OnCreate事件中初始化。
5. 全局变量
不推荐使用全局变量。但是,在某些时候必须使用时,应努力只在一段上下文范围内使用全局变量。例如,一个全局变量只应在一个单元的implemntation部分内是全局的。如果打算在多个单元类使用全局数据,应将它们移到一个公共的单元中然后被其它所有单元使用。
全局变量可以在var子句中直接初始化为一个值。所有的全局数据会自动初始化为0,因此不要将全局变量初始化为一个“空”值比如 0、nil、’’、Unassigned、等等。这样做的一个理由是因为零-初始化的全局数据在exe文件中不会占据任何空间。零-初始化数据被存储在一个虚拟的数据段,它在应用程序启动后被分配在一段内存中。非零-初始化的全局数据在硬盘的exe文件占用空间。
全局变量以大写 “G”开头。
3.4.5 常量
在Delphi中常量的定义有两种方式Const方式和Resourcestring方式,前者是常量命名的一般方式,后者定义的字符串常量被存储在程序的资源中的一个字符串表格中。不论用哪种方式定义常量,常量的命名必须以常量作用范围前缀(G、P、V分别代表常量作用范围为全局、单元、本过程)其后紧接与意义相关联的名称词干。名称词干为一到多个(不要太多,总长不得超过Delphi的限制且不得使用Delphi系统禁用的字母)英文单词或英文单词缩写,各英文字母全部大写。名称词干要考虑到描述对象单数复数,对复数应该在词干后面加上大写S 。例如:
序号 常量名称 Comments
1 P_CIRCELNUMBER 循环次数(单元)
2 G_SERVERNAME 服务器名(全局)
3.4.6 类型
1. 大小写规则
类型标识符是保留字,应当全部小写。Win32 API 类型常常全部大写,并且遵循诸如Windows.pas或其他A P I 单元中关于特定类型名的规则。对于其他变量名,第一个字母应大写,其他字母则大小写交错。下面是一些例子:
v a r
lM y S t r i n g : s t r i n g ;
// 保留字
lWi n d o w s H a n d l e : H W N D ;
/ / Win32 API 类型
I : I n t e g e r ;
/ /在S y s t e m 单元中引入的类型标识
2. 浮点型
不使用R e a l 类型,通常情况下,对于浮点数应当使用D o u b l e 。当需要比D o u b l e 提供的范围更大时,可以使用E x t e n d 。
3. 枚举型
枚举类型名必须代表枚举的用途。名称前要加T 字符作为前缀,表示这是个数据类型。枚举类型的标识符列表的前缀应包含2 ~ 3 个小写字符,来彼此关联。例如:
TSongType=(stRock,stClassical,stCountry,stAlternative,stHeavyMetal,stRB);
枚举类型的变量实例的名称与类型相同,但没有前缀T ,也可以给变量一个更加特殊名称,诸如
F a v o r i t e S o n g Ty p e l 、F a v o r i t e S o n g Ty p e 2 等等。
4. Va r i a n t 和O l e Va r i a n t
一般不建议使用Va r i a n t 和O l e Va r i a n t 。但是,当数据类型只有在运行期才知道时(常常是在C O M 和数据库应用的程序中),这两个类型对编程就有必要。当进行诸如自动化A c t i v e X 控件的C O M 编程时,应当使用O l e Va r i a n t ;而对于非C O M 编程,则应当使用Va r i a n t 。这是因为,Va r i a n t 能够有效地保存
D e l p h i 的原生字符串,而O l e Va r i a n t 则将所有字符串转换为O L E 字符串(即Wi d e C h a r 字符串),且没有引用计数功能。
3.4.7 构造类型
1. 数组类型
数组类型名应表达出该数组的用途。类型名必须由该类型的作用域范围加上字母T 为前缀。如果要声明一个指向数组类型的指针,则必须加字母P 为前缀,且声明在类型声明之前。例如:
type
V_PCycleArray = ^TCycleArray;
V_TCycleArray = array[1…100] of integer;
end;
2. 记录类型
记录类型名应表达出记录的用途。类型名必须必须由该类型的作用域范围加上字母T 为前缀。如果要声明一个指向记录类型的指计,则必须加字母P 为前缀,且其声明在类型声明之前。例如:
type
V_PEmployee = ^TEmployee;
V_TEmployee = record
V_EmployeeName : string;
V_EmployeeRate :do
uble;
end;
3.4.8 语句
1. If 语句
在i f / t h e n / e l s e 语句中,最有可能执行的情况应放在t h e n 子句中,不太可能的情况放在e l s e 子句中。为了避免出现许多i f 语句,可以使用c a s e 语句代替。如果多于5 级,不要使用i f 语句。请改用更清楚的方法。不要在i f 语句中使用多余的括号。如果在i f 语句中有多个条件要测试,应按照计算的复杂程度从右向左排。这样,可以使代码充分利用编译器的短路估算逻辑。例如,如果C o n d i t i o n 1 比C o n d i t i o n 2 快,C o n d i t i o n 2 比C o n d i t i o n 3 快,则i f语句应这样构造:
if Conditior1 and Condition2 and Condition3 then
2. case 语句
(1) 概述
c a s e 语句中每种情况的常量应当按数字或字母的顺序排列。
每种情况的动作语句应当简短且通常不超过4 ~ 5 行代码。如果动作太复杂,应将代码单独放在一个过程或函数中。C a s e 语句的e l s e 子句只用于默认情况或错误检测。
(2) 格式
c a s e 语句遵循一般的缩进和命名规则。
3. while 语句
尽量不使用E x i t 过程来退出w h i l e 循环。如果需要的话,应当使用循环条件退出循环。所有对w h i l e 循环进行初始化的代码应当位于w h i l e 入口前,且不要被无关的语句隔开。任何业务的辅助工作都应在循环后立即进行。
4. for 语句
如果循环次数是确定的,应当用f o r 语句代替w h i l e 语句。
5. repeat 语句
不允许使用repeat语句,统一使用while或for语句。
6. with 语句
(1) 概述
一个w i t h 语句只允许对单个对象或记录进行赋值时使用。例如:
with Record1,do
(2) 格式
w i t h 语句也遵循本章关于命名和缩进的规则。
3.4.9 结构化异常处理
1.概述
异常处理主要用于纠正错误和保护资源。这意味着,凡是分配资源的地方,都必须使用t r y. . . f i n a l l y来保证资源得到释放。不过,如果是在单元的初始/结束部分或者对象的构造器/析构器中来分配/释放资源则例外。
2. try. . . f i n a l l y 的用法
任何情形下,每一次的分配都应跟随一个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. try. . . e x c e p t 的用法
如果你希望在发生异常时执行一些任务,可以使用t r y. . . e x c e p t 。通常,没有必要为了简单地显示一个错误信息而使用t r y. . . e x c e p t ,因为A p p l i c a t i o n 对象能够自动根据上下文做到这一点。如果要在子句中激活默认的异常处理,可以再次触发异常。
4. try. . . e x c e p t . . . e l s e 的用法
不鼓励使用带e l s e 子句的t r y. . . e x c e p t ,因为这将阻塞所有的异常,包括你没有准备处理的异常。
3.4.10 类
1. 命名与格式
类的名称应当表达出类的用途。类名前要加字母T ,表示它是一个类型。例如:
t y p e
T C u s t o m e r = c l a s s ( TO b j e c t ) ;
类的实例名称与类名相同,只不过没有前缀T 。
v a r
C u s t o m e r : T C u s t o m e r ;
注意关于控件的命名,请参阅3.8 节“控件”。
2. 字段
(1) 命名与格式
字段的命名遵循与变量相同的规则,只不过要加前缀F ,表示这是字段。
(2) 可见性
所有字段必须为私有。如果要在类的作用域之外访问字段,可借助于类的属性来实现。
3. 方法
(1) 命名与格式
方法的命名遵循与过程和函数相同的规则。
(2) 静态方法
当你不希望一个方法被派生类覆盖时,应当使用静态方法。
(3) 虚拟方法与动态方法
当你希望一个方法能被派生类覆盖,应当使用虚拟方法。如果类的方法要被多个派生类直接或间接地使用,则应当用动态方法。例如,某一个类含有一个被频繁覆盖的方法,并有1 0 0 个派生类,则应将方法定义为动态的,这样可以减少内存的开销。
(4) 抽象方法
如果一个类要创建实例,则不要使用抽象方法。抽象方法只能在那些从不创建实例的基类中使用。
(5) 属性访问方法
所有属性访问方法应当定义在类的私有或保护部分。
属性访问方法遵循与过程和函数相同的规则。用于读的方法应当加G e t 前缀,用于写的方法应当加S e t 前缀,并且有一个叫Va l u e 的参数,其类型与属性的类型相同。例如:
TSomeClass = class(TObject)
private
FsomeField : Integer;
protected
function GetSomeField : Integer;
procedure SetSomeField(Value : Integer);
public
property SomeField : Integer read GetSomeField write SetSomeField;
end;
4. 属性
属性作为私有字段的访问器,遵循与字段相同的命名规则,只不过没有F 前缀。属性名应为名词,而不是动词。属性是数据,而方法是动作。数组属性名应当是复数,而一般的属性应当是单数。
5. 访问方法的使用
尽管不是必须,但还是建议你使用写访问方法来访问代表私有字段属性。
3.5 文件
3.5.1 项目文件
项目文件的名称应当具有描述意义,且以prj开头。例如,“The Delphi 5 Developer’s Guide Bug Manager ”的项目名称为PrjDDUBugs.dpr ,一个系统信息程序的名称为PrjSysInfo.dpr 。
3.5.2 窗体文件
窗体的命名必须以Frm(Form缩写)开头,其后紧接与意义相关联的名称词干。名称词干为一到多个(不要太多,总长不得超过Delphi的限制且不得使用Delphi系统禁用的字母)英文单词或英文单词缩写,各英文字母的第一个字母大写。名称词干要考虑到描述对象单数复数,对复数应该在词干后面加上小写s 。例如:
序号 窗口名称 说明
1 FrmAbout 关于本系统的版权信息
2 FrmSystemError 系统出错提示
3 FrmMain 系统主界面
4 FrmReportSheet 报表输出
3.5.3 数据模块文件
数据模块文件的名称应当表达出数据模块的作用,且以Dm开头。例如,Customers 数据模块的文件名叫DmCustomers.dfm。
3.5.4 远程数据模块文件
远程数据模块文件的名称应当表达出远程数据模块的用途,且以Rdm开头。例如: 自定义远端数据模板的文件名字应为RdmCustomers.dfm
3.5.5 单元文件
1.普通单元文件
窗体单元名,以“U”开头,再加上相应的窗体名。名称词干为一到多个(不要太多,总长不得超过Delphi的限制且不得使用Delphi系统禁用的字母)英文单词或英文单词缩写,各英文字母的第一个字母大写。名称词干要考虑到描述对象单数复数,对复数应该在词干后面加上小写s 。例如:
序号 单元名称 说明
1 UPublicVal 公用变量统一定义单元
2 UPublicFunction 公用函数统一定义单元
3 UFrmMain 主单元
4 UFrmAbout About窗口单元
单元文件应当按照以下的顺序包含下列元素:
版权/标识块注释
单元名
接口段
实现部分
一个结束符”end.
”
每个部分之间至少空一行。
其它的元素应当被结构化成你认为最适当的顺序。但文件注释应当出现在文件的最开始,然后是单元名,然后是任何条件定义、编译器指示符或包含语句,然后是uses字句:
//单元功能,创建人,创建日期,最近修改人,最后修改时间以及版本说明
unit UComObjectTest;
//interface部份只包含需要被外部单元访问的类型、变量、过程与函数的声明。而且,
//这些声明应当在I m p l e m e n t a t i o n 部分之前。
interface
//只包含该部分需要的单元。不要包含可能由D e l p h i 自动添加的单元
uses
ComObj, ActiveX, Project1_TLB, StdVcl;
type
TmyCom = class(TAutoObject, ImyCom)
protected
{ Protected declarations }
function Get_EditText:widestring;safecall;
end;
//包括本单元私有的类型、变量、过程与函数的实现。
implementation
//应当只包含该部分需要的单元,不要有多余的单元。
uses ComServ,SysUntils,unit1,ExtCtrls,Dialogs,typinfo;
{ TmyCom }
function TmyCom.Get_EditText: widestring;
begin
end;
end.
2. 窗体单元
窗体单元文件的名称在相应的窗体名称前加上U。例如,A b o u t 窗体的单元名称叫FrmAbout.dfm,主窗体的单元文件名称叫UFrmAbout.pas。
3. 数据模块单元
数据模块单元文件的名称与相应的数据模块名称相同。例如,一个自定义数据模板单元的名称应为DmCustomers.pas。
4. 通用的单元
一般目的单元的取名应符合使用该单元的目的。例如,一个包含全局变量的单元取名为UCustomerGlobals.pas。
注意,该单元的名字不能与它的工程中所使用的所有包中的单元的名字相同。不赞成使用一般的或通用的单元名字。5. 控件单元
控件单元应放在单独的路径中,以表明它们是定义控件的单元。它们一般与项目不放在同一路径下。单元文件名称应表达出其内容。
3.6 窗体与数据模块
3.6.1 窗体
1. 窗体类型的命名标准
窗体类型的名称应当表达出窗体的用途,且要加T 前缀,后跟Frm和描述性名。例如,
A b o u t窗体类型名称为:
TAboutFrom = class(TForm);
主窗体的类型名称为:
TMainForm = class(TForm);
客户登录窗体的类型名称为:
TCustomerEntryForm = class(TForm);
2. 窗体实例的命名标准
窗体实例的名称与相应的类型名称相同,但没有前缀T 。例如,前面提到的窗体类型与实例的名称为:
类型名 实例名
TFrmAbout FrmAbout
TFrmMain FrmMain
TFrmFormCustomerEntry FrmFormCustomerEntry
3. 自动创建的窗体
除非特别原因,只有主窗体才自动生成。其他所有窗体必须从Project Options 对话框的自动生成列表中删除。
4. 模式窗体实例化函数
所有窗体单元都应当含有实例化函数,用于创建、设置、模式显示和释放窗体。这个函数将返回由窗体返回的模式结果。传递给这个函数的参数遵循参数传递的规则。之所以要这样封装,是为了便于代码的重用和维护。窗体的变量应当从单元中移走,改在窗体实例化函数中作为局部变量定义(注意,要求从P r o j e c tO p t i o n s 对话框的自动生成列表中移走该窗体。请看前面的内容)。
3.6.2 数据模块
1. 数据模块的命名标准
数据模块类型名称应表达出它的用途,且要加前缀T ,后跟描述性名称,最后是DataModule 。
例如,一个自定义的数据模板有时候应该象:
TCustomerDataModule = class(TDataModule)
一个命令式的数据模板的名字应象:
TOrdersDataModule = class(TDataModule)
2. 数据模块实例的命名标准
数据模块实例的名称应当与相应的类型名称相同,但没有前缀T 。例如,前面的数据模块类型、实例名称如下:
类型名称 实例名称
TCustomerDataModule CustomerDataModule
TOrdersDataModule OrdersDataModule
3.7 包
3.7.1 运行期包与设计期包
运行期包中应当只包含所需要的单元。那些属性编辑器和控件编辑器的单元应当放在设计期包中。注册单元也应当放在设计期包中。
3.7.2 文件命名标准
包的命名遵循下列模式:
FhdLibXxxvv.pkg — 设计期包
FhdStdXxxvv.pkg — 运行期包
其中,Fhd 代表一个3 字符的前缀,用于标识公司。v v 代表包的版本号,其中也包含了Delphi 的版本号。注意包名称中的lib 或std 分别表示这是设计期包还是运行期包,Xxx表示包的内容。例如:
FhdStdAdo50.pkg — 设计期包
FhdLibAdo50.pkg — 运行期包
3.8 控件
3.8.1 自定义控件
1. 控件类型的命名标准
控件的命名与类的命名类似,只不过它有3 个字符的前缀。这些前缀用以标识公司、个人或其他实体。公司统一为 : Fhd。
2. 控件单元
控件单元只能含有一个主要控件,这是指出现在控件选项板上的控件。其他辅助性的控件或对象也可以包含在同一单元中。
3. 注册单元
控件的注册过程应当从控件单元中移走,放在一个单独的单元中。这个注册单元用于注册所有控件、属性编辑器、控件编辑器、向导等。控件注册应当在设计期包中进行。因此,注册单元应当包含在设计期包而不是运行期包中。建议注册单元这样命名:
F h d R e g . p a s
其中,Fhd 为3 个字符前缀,以标识公司。
3.8.2 标准控件的命名规范
控件的命名必须以控件类型的英文缩写开头,其后紧接与意义相关联的名称词干。名称词干为一到多个(不要太多,总长不得超过Delphi的限制且不得使用Delphi系统禁用的字母)英文单词或英文单词缩写,各英文字母的第一个字母大写。名称词干要考虑到描述对象单数复数,对复数应该在词干后面加上小写s
例:
序号 控件名称 控件缩写 控件命名范例
1 TButton Btn BtnOk
2 TPictureButton Pcb PcbThankInfo
3 TCheckBox Chb ChbAgeShow
3.8.3 标准控件缩写标准
见附页
4 编码规范
在编码过程中,应该遵守如下规则:
· 多写注释文字.
· 数据与界面分离.
· 减少资源占用.
· 不采用没有源代码的第三方控件.
· 合理的异常处理.可以处理意外情况时不要随便使用try except等
· 重视每一个编译器报警.尽量消除报警.
除了以上所提到的基本要求外, 具体项目由项目负责人决定更细致更严格的要求.
代码书写规范
· 源程序每个文件控制在1000~2000行
· 每个函数行数限制在200行之内
· Delphi 2格缩进
· 函数要有说明,至少一行
· 每个接口(全局)函数的入口出口参数要加注释
· 每条语句必须在Delphi规定的打印线内
4.1 过程及函数的编码规范
4.1.1 注释
1.位置要求:
1)注释行的长度以在最大化窗口内可以看到全部内容为宜,如果一行不够显示需要换行,下一行注释语句与上一行注释语句应对齐。
2)变量申明的注释放在变量申明语句的后面,并以 // 为注释语句
3)注释行一律放在被注释语句的上一行。
4)注释行中,注释命令与注释内容空一个空格,如:
var
V_BpMode:String;
// 用户服务类型
2. 在函数、过程、模块、单元、类的开始处严格按如下格式写出注释:
// 过程(或函数)名:
// 功能描述:
// 参数说明:
// 返回值:
// 时间:
// 修改者:
// 修改时间:
// 该调用其它模块说明
// 调用该模块的其它模块说明
3.逻辑上多重嵌套的情况,如try …. Finnaly;
if …. then
…;
begin
d end;
while语句 ;for 语句等,需要加配对注释
例:
如果出现多重嵌套语句,如多重if , while , try , for 等,应加上配对注视
多重if 注视要求:
if 条件1 then
begin
if 条件2 then
begin
end ;
// end of if 条件2
end ;
// end of if 条件1
多重while , for 注视要求同 if 语句
多重try 注视要求:
try{ // try1
try{ // try2
try{ //try3
}finally // end of try3
}finally // end of try2
}finary // end of try1
4. 请在各程序段加上程序思路说明。
4.1.2 变量取名及含义
变量取名请遵守命名规范,对使用频繁、关键变量,为了便于阅读和修改,在定义时必须加上注释标明其含义。
4.1.3 书写格式
1. 用分层缩进的写法显示嵌套结构的层次;
2. 在注释段与程序段、以及不同程序段插入空行;
3. 每行只写一条语句。
5 界面
5.1 总体要求
系统界面风格采用与Windows操作系统一致。
5.2 屏幕分辨率及颜色设置
程序设计、开发时采用800*600分辨率,16位增强色,小字体;
在同一窗口中除黑、白、深灰、灰色外,最多使用四种彩色:
l 红色用于表示危险、停止或红头文件头;
l 黄色表示注意;
l 绿色表示安全,可以执行;
l 蓝色表示确定。
5.3 窗口大小及操作方式
主控窗口大小按满屏设计,在系统实际运行时可根据客户端的分辨率及任务栏设置(自动隐藏或不自动隐藏)自动进行控件的位置、间距的调整。
其它窗口(如系统载入窗、用户登录窗、信息提示窗等)则根据实际需要设计,在兼顾系统实际运行时客户端分辨率及任务栏设置的前提下,尽量固定其大小。
使用菜单与工具条相结合、鼠标与键盘操作相结合的方式;菜单项及工具条按钮均应在主控窗口的状态提示区提供信息提示功能并设置快捷键,保证用户在脱离鼠标的情况下也可通过键盘来操作。
5.4 控件设计
工具条按钮尽量采用Windows常用按钮,如在下表中已存在的按钮,则系统中应采用
说明 按钮样式 说明 按钮样式
新建(Ctrl+N) 复制(Ctrl+C)
打开(Ctrl+O) 剪切(Ctrl+X)
删除 粘贴(Ctrl+V)
邮件 帮助主题
历史记录 在线帮助
预览 撤消操作
打印 重复操作
记录控制条 选择
查找(Ctrl+F) 继续查找
复制记录 信息显示
粘贴记录 向上
撤消记录 向下
记数 保存当前
结构 保存全部
升序排列 降序排序
5.5 窗口设计
5.5.1 字体
Ø 窗口中非标题对象字体一般采用宋体9号字;
Ø 标题字体采用宋体14号粗体字。
5.5.2 边框
Ø 窗体中的Label对象为无边框;
Ø 编辑框、选择框、检查框、列表框统一为三维下凹单线边核边框;
Ø 按钮为三维上凸单边框。
5.5.3 颜色
Ø 标签对象(Label)的颜色为黑色透明;
Ø 编辑框、选择框、检查框、列表框字体颜色为:黑色白底,全部选择时的颜色为白色兰底,不可编辑时的颜色为,灰色白底。
5.5.4 对齐方式
Ø 所有窗体中的对象尽量采用右对齐的方式
Ø Form的Scaled属性一律设为False.
Ø 采用先从左到右,再从上到下的次序。
5.5.5 页面布局
Ø 尽可能少用滚动条,当页面内容较多时尽可能使用Page Control的方式进行布局;
Ø 使用CheckBox和RadioButton时,对于同一类别的选择应使用GroupBox将它们分类。
附页:
标准控件前缀命名
Standard页
前缀 构件
mm TMainMenu
pm TPopupMenu
mmi TMainMenuItem
pmi TPopupMenuItem
前缀 构件
lbl TLabel
edt TEdit
mem TMemo
btn TButton
cb TCheckBox
rb TRadioBox
lb TListBox
cmb TComboBox
scb TScrollBar
gb TGroupBox
rg TRadioGroup
pnl TPanel
cl TCommandList
Additional页
bbtn TBitBtn
sb TSpeedButton
me TMaskEdit
sg TStringGrid
dg TDrawGrid
img TImage
shp TShape
bvl TBevel
sbx TScrollBox
clb TCheckListbox
spl TSplitter
stx TStaticText
cht TChart
Win32页
tbc TTabControl
pgc TPageControl
il TImageList
re TRichEdit
thr TTrackBar
prb TProgressBar
ud TUpDown
hk THotKey
ani TAnimate
dtp TDateTimePicker
tv TTreeView
lv TListView
hdr THeaderControl
stb TStatusBar
tlb TToolBar
clb TCoolBar
System页
tm TTimer
pb TPaintBox
mp TMediaPlayer
olec TOleContainer
ddcc TDDEClientItem
ddci TDDEClientItem
ddsc TDDEServerConv
ddsi TDDEServerItem
Internet页
csk TClientSocket
ssk TServerSocket
wbd TWebDispatcher
pp TPageProducer
tp TQueryTableProducer
dstp TDataSetTableProducer
nmdt TNMDayTime
nec TNMEcho
nf TNMFinger
nftp TNMFtp
nhttp TNMHttp
nMsg TNMMsg
nmsg TNMMSGServ
nntp TNMNNTP
npop TNMPop3
nuup TNMUUProcessor
smtp TNMSMTP
nst TNMStrm
nsts TNMStrmServ
ntm TNMTime
nudp TNMUdp
psk TPowerSock
ngs TNMGeneralServer
html THtml
url TNMUrl
sml TSimpleMail
Data Access页
ds TDataSource
tbl TTable
qry TQuery
sp TStoredProc
db TDataBase
ssn TSession
bm TBatchMove
usql TUpdateSQL
Data Controls页
dbg TDBGrid
dbn TDBNavigator
dbt TDBText
dbe TDBEdit
dbm TDBMemo
dbi TDBImage
dblb TDBListBox
dbcb TDBComboBox
dbch TDBCheckBox
dbrg TDBRadioGroup
dbll TDBLookupListBox
dblc TDBLookupComboBox
dbre TDBRichEdit
dbcg TDBCtrlGrid
dbch TDBChart
Decision Cube页
dcb TDecisionCube
dcq TDecisionQuery
dcs TDecisionSource
dcp TDecisionPivot
dcg TDecisionGrid
dcgr TDecisionGraph
QReport页
qr TQuickReport
qrsd TQRSubDetail
qrb TQRBand
qrcb TQRChildBand
qrg TQRGroup
qrl TQRLabel
qrt TQRText
qre TQRExpr
qrs TQRSysData
qrm TQRMemo
qrrt TQRRichText
qrdr TQRDBRichText
qrsh TQRShape
qri TQRImage
qrdi TQRDBMImage
qrcr TQRCompositeReport
qrp TQRPreview
qrch TQRChart
Dialogs页
对话框构件是由构件封装的真正的窗体,因此,它们应遵循窗体的命名约定。类型已由构件的名称定义。它的实例的名称是Delphi自动生成的类型实例名字去掉数字后缀。举例如下:
TOpenDialog OpenDialog
TSaveDialog SaveDialog
TOpenPictureDialog OpenPictureDialog
TSavePictureDialog SavePictureDialog
TFontDialog FontDialog
TColorDialog ColorDialog
TPrintSetupDialog PrintSetupDialog
TFindDialog FindDialog
TReplaceDialog ReplaceDialog
Win3.1页
dbll TDBLookupList
dblc TDBLookupCombo
ts TTabSet
ol TOutline
tnb TTabbedNoteBook
nb TNoteBook
hdr THeader
flb TFileListBox
dlb TDirectoryListBox
dcb TDriveComboBox
fcb TFliterComboBox
Samples页
gg TGauge
cg TColorGrid
spb TSpinEdit
spe TSpinEdit
dol TDirectoryOutline
cal TCalendar
ibea TIBEventAlerter
ActiveX页
cfx TChartFX
vsp TVSSpell
f1b TF1Book
vtc TVTChart
grp TGraph
Midas页
prv TProvider
cds TClientDataSet
qcds TQueryClientDataSet
dcom TDCOMConnection
olee TOleEnterpriseConnection
sck TSocketConnection
rms TRemoteServer
mid TMidasConnection