编程规范(PB)
1 简介
1.1 简介
这个文档描述了用于编写稳定、可靠的PowerBuilder应用程序的一些标准、约定和准则。 他们基于合理的,经过证实的一些使代码容易理解、 维护和增强的软件工程的原则。另外,遵循这些标准,你作为一个PowerBuilder程序员的生产力将有一个显著的提高。一些经验证明,花时间在项目的开始写出高质量的代码,可以使在后来的开发过程中容易修改它,从而事半功倍。最后,遵循这一系列编码规范,可以使一个开发团队更好地保持一致性,最终必将极大地提高团队的生产力。
1.2 最初的准则和最终的准则
当你无法找到一些你需要的原则或准则时,或者它们很明显地不适用,或者其它的一些情况下,请使用常识,按照一些基本的原理去作。这个原则凌驾于其他原则。
2 命名规范
2.1 一般性约定
1.使用英文或汉语拼音的全称去准确地描述各种对象、变量 例如,ls_UserName (用户名) ,ldc_GrandTotal(总计)等等。尽管x1,y1这样的名称很容易拼写,因为它们很短,但是他们不可能明确地提示名称的含义,将导致代码难以理解、维护和改进。
2.使用大小写混合的方式命名
3.以合适的方式使用缩写 例如ll_RownNmber,简写为ll_RowNum是可以理解的,但是li_ReturnCode简写为li_rc就不一定被别人看懂,所以应该以尽量保守的态度使用缩写,在更多的时候使用全称,或者建立常用缩写的对照表。
4.避免太长的名称,尽量限制在15个字母以内 长名称虽然很容易懂,但特别长将导致拼写时经常出错。
5.不要在第一个字母和最后一个字母使用下划线
6.保持命名的一致性。相关的东西应给以相关的名字,以说明他们的关系和差异
2.2 具体约定
2.2.1 对象命名规范
<前缀>_名称
前缀 |
说明 |
m |
菜单(Menu) |
n |
标准用户对象(Standard class user object) |
n_cst |
定制用户对象(Custom class user object) |
u |
可视用户对象(Visual user object) |
d |
数据窗口(Datawindow) |
w |
窗口(Window) |
s |
全局结构(Global structure) |
注:名称为英文,新建对象必须加注释(菜单对象可例外)。一般情况下,菜单对象的名称与其所属窗口的名称一致。
例子:
w_master , m_master , d_cig_cd
u_tvs is the TreeView visual user object
u_dw is the DataWindow visual user object
n_cst_dwsrv is the custom class user object for DataWindow services
n_tr is the transaction standard class user object and is in the extension level
2.2.2 变量范围命名规范
<范围><数据类型>_变量名
范围:
范围 |
说明 |
a |
事件或函数的参数(Argument to an event or function) |
g |
全局变量(Global variable) |
i |
实例变量(Instance variable) |
l |
局部变量(Local variable) |
s |
共享变量(Shared variable) |
对于标准数据类型:
数据类型 |
说明 |
a |
Any |
blb |
Blob |
b |
Boolean |
ch |
Character |
d |
Date |
dt |
DateTime |
dc |
Decimal |
dbl |
Double |
e |
Enumerated |
i |
Integer |
l |
Long |
r |
Real |
s |
String |
tm |
Time |
ui |
UnsignedInteger |
ul |
UnsignedLong |
例子:
as_unitcode 表示事件或函数的输入参数,string类型
idc_val 表示实例变量,decimal 类型
li_row 表示局部变量,integer 类型
gd_firstday 表示全局变量,date类型
对于常用参照数据类型(reference variables):
数据类型 |
说明 |
ds |
DataStore |
dw |
DataWindow |
dwc |
DataWindowChild |
dwo |
Dwobject |
lvi |
ListViewItem |
mm |
MailMessage |
mr |
MailRecipient |
ms |
MailSession |
str |
Structure |
tr |
Transaction |
tv |
TreeView |
tvi |
TreeViewItem |
w |
Window |
例子:
datastore lds_unit
DataWindowChild ldwc_cig
window lw_code
注:
1) 尽量避免使用全局变量。
2) 全局变量和实例变量必须加注释(说明该变量在何处设置和使用);重要的局部变量加注释
4)全局变量使用具有说明性(名字足够长)的名字,局部变量用短名字
5)按常规方式使用的局部变量可以采用极短的名字。例如:用i、j作为循环变量
例如:在window的open()事件中对统计日期id_date赋值,在dw_unit.itemchanged()和cb_ok.clicked()中使用,则定义如下
//Set: open
//Use: dw_unit.itemchanged, cb_ok.clicked
Date id_date //统计日期
2.2.3 函数命名规范
<前缀>_ FunctionName
前缀 |
说明 |
wf |
窗口函数 |
of |
对象函数 |
f |
全局函数 |
例子:wf_GetTime, of_ GetTime, f_ GetTime
注:不使用全局函数(使用用户对象封装);函数名采用动作性的名字,后面可以跟着名词
2.2.4 窗口中控件命名规范
<前缀>_名称
前缀参照PowerBuilder的缺省规定
对于下拉数据窗口,使用如下命名方式:d_dddw_ + name
另外,如果同类控件在窗口中出现两次以上,名称必须为英文,不能是数字。
例如:在同一窗口中有两个CommandButton,不能命名为cb_1和cb_2,,必须是有意义的名称,如cb_ok和cb_cancel。
2.2.5 数据库对象命名规范
数据库对象包括表、视图、触发器及存储过程等
库名: 英文前三个字母
表命名: 小写,应尽量用英文,也可用拼音,视情况而定;表名前加比较短小的业务名称,推荐用两位汉语拼音简写 (例如,储运,cy) ;主从表的命名,主表名_s;_s1;_s2;代码表后面加_cd;表名尽量短小精焊
视图命名: v_名称,名称为表名或主要表名
触发器命名: ti_表名 (insert trigger)
td_表名 (delete trigger)
tu_表名 (update trigger)
tui_表名,tud_表名,tid_表名,tuid_表名 (复合 trigger)
存储过程: sp_名称
列名: 小写,连接符使用下划线;字符型尽量用varchar,尽量加长。
常用列名或列名后缀:
代码:_cd;无意义:_id;名称:_nm;金额:_mny;数量:_qty;日期:_dt;标志:_mark;
人:_er或_or;类型:_tp;审核人:verifier;部门:_dept;编号:_no;计量单位:jldw;大小:sz;重量:wg;备注:rem;率:_rate;制单人:maker;时间:_tm;开始时间:start_dt;结束时间:end_dt;批号:bat_no;周期:cycle
3 表达式和语句
1. 使用缩行显示程序的结构。采用一种一致的缩行风格,是使程序呈现出结构清晰的最省力的方法
2. 使用表达式的自然形式。例如:
IF (Not (ldc_BlockId < ldc_ActBlks) Or Not (ldc_BlockId >= ldc_ActBlks)) Then
在上面的语句中两个测试都用到了否定,而他们是不必要的,应该改变关系运算符的方向,是测试变成肯定的:
IF ((ldc_BlockId >= ldc_ActBlks) Or (ldc_BlockId < ldc_ActBlks)) Then
3. 用加括号的方式排出二义性。括号表示分组,即使有时并不必要,加了括号也可能把意图表示的更清楚,上面的例子中,内层括号就不是必须的。
4. 分解复杂的表达式。
5. 当心副作用。像 ++ 这一类的运算符具有副作用,它们除了返回一个之外,还将隐含地改变变量的值。
4 界面设计
4.1 一般性约定
界面设计是软件设计中很重要的一部分,一些优秀的系统大都拥有优秀的界面设计,一些大公司的界面设计往往精确到像素。但是,很多人对优秀界面的理解就是“漂亮”甚至说“花哨”,而忽视了更重要的东西,这就有些不妥了。那么一个优秀的设计应该具有什么样的特征呢?
1、功能性 界面设计必须符合功能的需要,这个是最重要的,界面是用户使用系统的途径,优秀的界面必须与功能的需求相统一。应该重点突出,结构清晰,布局具有整体感。用类似winamp的用户界面来处理数据应用的界面,就有点不伦不类了。
2、导航 优秀的界面应该给用户舒适的导航,用户可以很容易找到相应的功能,或者可以引导用户正确的操作,避免错误。重点的元素放在醒目的地方。
3、友好 尽量不要出现用户看不明白的提示、专业术语或错误信息。
4、操作性 一个优秀的界面设计,必须具有良好的操作性,符合大多数人的操作习惯,对于特殊应用,可快速操作也很重要。
5、时尚性 密切注意流行界面的发展方向,当然也不是盲目跟从。比如win98时代就不要再开发win32风格的界面了。
那么开发时应注意什么呢?
1、整个系统应该风格统一,不要前后矛盾,比如前一个窗口中红色代表错误,在接下来的提示中又用红色来表示重要信息。
2、不要使用让用户产生歧义的图标、图形或文字,比如有人在退出按钮上写上“逃离”,又如,保存按钮写“就这样吧”等等。。
3、尽量不要使用activeskin之类的换肤软件,其一这些皮肤其实并不美观,其二增加了系统出错机会,加大系统开发复杂度。
4、合理的结构设计,可能的情况下,将界面设计与业务逻辑独立开来,尽量不要将业务逻辑写到界面之中,比如有人在“确定”按钮里写了几百行的代码,所有功能都在里面了。
5、导航深度不要超过3层,有的设计往往要好几级菜单下才能找到相应的功能。还有的功能必须要层层打开n个窗口后,才在一个角落里发现打开它的按钮。
6、不要使用太扎眼的元素,比如颜色,线条等。例如一个使用亮绿色的提示窗口会让用户睁不开眼睛
7、窗口元素布局要整齐划一,比如即使用不了那么长的文本框,也要使它与上面的文本框一样长
8、不要在界面上出现可有可无的东西,有人用了一半的窗口面积描述这个窗口各个按钮的使用方法,此举纯属画蛇添足,因为一个熟练的用户闭着眼睛都知道下一步该按哪个键,当然面向大众的软件例外。
。。。。。。。
4.2 具体约定
1、 界面(包括Window和DataWindow)应在800*600分辨率下设计(同时应支持其它分辨率);整个系统一般使用9号宋体,个别情况(如标题)用大字体(14号宋体)
2、 同一窗口界面中颜色不能超过4种
3、 DropDownDataWindow的风格用Tabular,白底黑字,下拉后不能显示所有记录时,必须加垂直滚动条;grid 风格的DataWindow不要用下凹和灰底,在"Summary" 段加合计,显示共多少条记录等信息
4、 CommandButton 不能出现在左面和上面,不要紧贴窗口边界;普通CommandButton大小为352*92。当与SingleLineEdit等其它控件合用时(如:在SingleLineEdit输入查询,在右面有一查询按钮),可以放在上面,并用Group围往
5、 不能含有无用的隐藏控件;不要用隐藏的datawindow, 用datastore代替
6、 按MDI风格设计,除主窗口上的菜单可带有toolbar外,其他窗口少用toolbar
7、 多个RadioButton(其中一个必须为Checked)和CheckBox用Group围住,点击后不能出现打开窗口等类似按钮的动作
8、 TabPage要有图标
10、所有的日期用yyyy-mm-dd格式
11、DataWindow的BorderStyle为StyleLowered,主细窗口之间的距离不超过20 PBU,宽高的设置应尽量避免横竖滚动条的同时出现
12、窗口中的左上角和右下角的控件距窗口边界的距离为X:64PBU,Y:56PBU(14个Pixels)
13、 FreeForm类型的录入数据窗口,Text和Column的高度为56 PBU,一对Text和Column,之间的距离为0;Text后加单字节冒号“:”,右对齐;Column加下划线,左对齐;不可录入的Text和Column的Taborder为0,颜色为Navy
14、 Grid类型的录入数据窗口,Header和Detail的高度为84;标题不加粗,中间对齐;最左列加“行号”(如果无行号字段,用计算域getrow()),中间对齐;所有数字列右对齐,其它列左对齐,都为白底黑字;小计、合计的颜色为Navy,中间对齐,放在下面。不可录入的Grid数据窗口,去掉MouseSelection属性,否则点中字段后会出现黑块
15、对于不用做主细录入的Grid型数据窗口,标题和行号可以用灰底凸起形式
日期字段用EditMask(yyyy-mm-dd),不用下拉日历,否则会出现时分秒
16、所有菜单的后面必须有加速键,加速键为半角圆括号括起的大写英文字母,同级菜单中不能用相同的加速键。第一个菜单中的最后一个菜单项是退出系统[Ctrl+X],上面为横线
5 注释约定
5.1 注释的一般性约定
1、注释使你的代码更整洁 你为你的代码写注释使为了使你的代码更容易被你、你的合作者、以及后来参与这个项目的任何其他程序员更好的理解你的代码。
2. 保持注释的简单 一些好的注释是简单的。你没有必要象写书一样的写注释,你只要提供充分的信息使别人理解你的代码就可以了。
3、在注释中要写明为什么要写这段代码,而不仅仅是这段代码在做什么 例如
§ If ldec_ GrandTotal >= 1000.00 Then
§ ldec_GrandTotal = ldec_GrandTotal * 0.95
§ End If
§ 上面的代码显示总计大于1000时,将总计乘以0.95,为什么要这样做? 是否有商业规则要求大额合同可以得到折扣?这种折扣是有时间限制的还是一直沿用?或者是这个程序员的慷慨大方?除非在某个地方有这方面的说明,否则你不可能明白。
5.2 注释的具体约定
5.2.1 函数的注释约定
函数注释风格常常是函数是否易于理解、维护和改进的关键因素。
每个函数前需要有如下格式的函数说明
//////////////////////////////////////////////////////
// 函数名: of_init
//
// 访问权: public
//
// 描述: 从ini文件的某个段中读取值来初始化对象的属性
// 如果没有取到值,属性被赋值为空字符串''
//
// 参数:
// as_inifile 函数要读取信息的ini文件的名称
// as_inisection ini文件的段名
//
//
// 返回值: integer
// 1 正确
// -1 有错误发生
//
// 作者:闫修华 时间:
//
///////////////////////////////////////////////////////
//
// 修改
//
// 作者:闫修华 时间:
// 原因:
//
//////////////////////////////////////////////////////
除此之外,还可能包含如下信息:
· 如果函数内部调用了其他自定义函数,应予以说明。
· 如果该函数只能与其他函数配合使用,请注明与之有关联的其他函数
· 如果函数有缺陷,请予以注明
· 如果函数隶属于其他对象,例如窗口函数、用户对象函数等,可能在函数中改变此 对象的一些属性,此时需要在函数中予以说明。
· 在函数的注释中,不仅应该描述函数做了什么,还应包含函数为什么要这样做。以 便别人很快理解你的编程思路。
5.2.2 自定义事件的注释约定
事件需要下面有类似的说明:
//////////////////////////////////////////////////////
//
// 事件名: ue_deleterow
//
// 描述: 删除当前行或选中行
//
// 参数表: (空)
//
// 返回值: integer
// 1 成功删除行
// 0 行没有被删除
// -1 发生错误
//
// 作者:闫修华 时间:
//
//////////////////////////////////////////////////////
// 修改:
//
// 作者:闫修华 时间:
// 原因:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
//
//////////////////////////////////////////////////////
除了事件应该有的注释之外,自定义事件的注释还应该包括:
· 为什么要定义这个事件
· 何时触发
· 参数说明
6 书写整洁的代码的技巧
- 常量全部大写
- 声明变量时,
声明变量时,每个变量占一行,后面加注释来描述它的用途。使用tab分隔变量类型和变量名,以保证上下两行的排列整齐,如:
long ll_CurrentRow //当前行号
string ls_Name //名字
而不是:
long ll_CurrentRow //当前行号
string ls_Name //名字
- 不可以以st_1,dw_1,cb_1来命名对象或控件
- 书写代码的过程中使用分段和缩进
- 使用空白 例如:
li_ModifiedNumber + li_DeletedNumber = li_Total,
不要写成
li_ModifiedNumber+li_DeletedNumber=li_Total
- 使用Tab键而不是空格键来缩排循环中的代码及其他复合语句,以显示包含关系。
- 在所有运算符(+,-,*,/)及赋值动词(=)的前面和后面都要加上一个空格,
并且在函数参数表中的每一个逗号后面也要加一个空格。如:
string ls_Value
ls_Value = gf_GetSystemSet("
dw_maint.SetItem(Row,
而不是
string ls_Value
ls_value=gf_getSystemSet("
dw_maint.SetItem(row,
- 数据库命令(例如,INSERT,SELECT以及DECLARE CURSOR)应全部大写,
而域名则小写并且PowerBuilder约束变量应使用与普遍变量同样的约定。 - Powersoft的函数和命令的每一个单词的第一个字母都应该大写或全部小写
(例如,If,RightTrim(),而不是IF, RIGHTTRIM())。 - 在行延续时应把连接标记(例如AND,+)放在行的末尾而不要放在下一行的开始处。
- 单行结构的语句应分解为多行:
If ll_Rows > 6 Then
dw_report.Retrieve()
End If
而不用下面的写法:
If ll_Rows > 6 Then dw_report.Retrieve()
7 遵循30秒原则
任何程序员可以在30秒之内读懂你写的一段代码。如果不能,说明这段代码太长了,应该把其中的一部分封装起来,写成一个函数。
8 修改规范
8.1 增加代码
§ //added by闫修华 @
§ //增加的原因(如果原因很明显,可以不写)
§ 增加的代码……………
§ //added by闫修华 @
8.2 修改代码
§ 首先将原来的代码注释掉
§ /*commented by闫修华 @
§ 修改原因
§ ………………
§ ………………
§ commented by闫修华 @
§ 然后增加修改的代码
§ //new script added by闫修华 @
§ 修改的代码…………
§ //new script added by闫修华 @
8.3 删除代码
§ /*deleted by闫修华 @
§ 删除原因
§ 删除的代码…………
§ deleted by闫修华 @