作者:达通兴电脑科技公司(www.study01job.com) 郭宝利
一、安全的应用软件
在应用软件的开发中,重要的一个因素是要给用户提供一个安全的工作环境,在软件中不应藏有任何“地雷”,在用户将要进行破坏性的且难以恢复的操作时,系统应当给予应有的提示,
提高PB程序的健壮性
。用户只有充分相信软件是安全的,才会乐于使用它,才会放心地去使用它,才能更高效地去探索这一软件所提供的新功能。二、什么是安全的应用
最重要的,但也是最不容易实现的是排除可能会使应用非正常终止的错误。在任何情况下,最终用户都不应看到应用出现保护性错误而退出系统,这种错误最容易使用户对软件失去信心。因为这意味着用户要中断思路,并费时费力地重新登录,而且已进行的操作也会因没有存盘而全部丢失。当然造成系统终止的原因很多,可能是网络、硬件、系统软件或是 PowerBuilder本身的问题,但是开发者应当尽量周全地考虑到各种可能发生的问题,使出错的可能降至最小。特别是使用PowerBuilder开发的软件的确经常会出现保护性错误,但是开发人员却不能因此怨天尤人,而是要多做测试,选择最为保险的方法实现相同的功能。
此外,在使用PowerBuilder编程时,还有一种常见的导致非正常终止的情况是由于程序员自己的原因造成的,这就是变量联接滞后问题,即在编译时定义一个有效的对象类,但是在运行时却没有创建它的实例或这个实例已注销(destroy);这时如有一段代码引用到这一对象,系统却无法在内存中找到它的实例,由此导致应用终止。所以,在引用变量时,应当首先检查它是否存在实例,例如,在一个窗口中引用了另外一个窗口的对象,就应首先检测它在执行代码之前是否已经创建了一个实例。
在下面的例子中,win_A这一窗口对象可能在代码执行时并没有创建,因此就应当在执行前用IsValid函数来检查其是否有效:
If IsValid(win_A) Then
Close(win_A)
End If
三、使用数据窗口中应注意的问题
PowerBuilder的代码将引用很多数据窗口中的列,指代这一列的方法可以是列名也可以是列号。列号是指这一个数据窗口在执行 SELECT语句中排列的顺序号,如果习惯于使用列号引用某列,要注意可能会在数据窗口的SELECT语句中移动或删除某些列,如果程序员想不起所有引用过这个数据窗口的代码,这时就有可能出现数据类型不匹配的错误。使用列名来引用则可以避免这类错误,但是这里使用的字符串在编译时PowerBuilder并不验证引用得是否正确,只有在运行时,系统才可能发现使用的字符串在数据窗口中不存在,并提示错误,退出应用。这种错误一般比较难以发现,一个有效的方法是尽可能使用Object Browser来剪贴,以减少录入错误。
安全的环境还应当注意尽可能避免用户无意中录入无效的数据。在GUI下,有许多控件可以以十分友好的方式限制用户输入值的种类。例如一个多选框只有两种值的选择,所以当用户做出选择的可能性只有两个时,可以采用这一控件,免去了另外编程进行输入有效性验证的麻烦。当选择的可能再多一些时,可以采用单选钮,每一种选择都是有效的,用户不可能输入任何一种无效的选择。同理,采用ListBox,DropDownDataWindow和DropDownListBox等标准控件都可以有效地避免用户无效输入,而不必另外编程来进行有效性验证,同时可避免用户在某一个输入点反复做输入尝试而耽误很多时间。
在一个应用系统中,开发者应当避免用户做出未经授权或没有意义的操作,在PowerBu- ilder中菜单和按钮等对象有Enabled和Visible属性,因此对用户未授权或无法进行的操作应将相应对象的属性改为Disabled和Invisible。例如,在一个窗口中有一个数据输入窗口和一个删除按钮,在编辑一条新记录时,删除按钮是无效的,因此,这个按钮的属性应为Disabled。
当窗口的状态发生变化时,应当随时改变控件或菜单项的这两个属性,
电脑资料
《提高PB程序的健壮性》(https://www.unjs.com)。当对象无效时,使用该控件的Disabled属性还是Invisible属性是个人习惯问题。一般地,在一个菜单项或控件永远是无效时应当使用Invisible属性,例如,一个用户打开一个有删除按钮的窗口,但是这个用户没有删除权限,那么这个按钮就应当是不可见的;而如果用户有权删除,只是在当前状态下,无法执行删除功能,如编辑新记录,这时该按钮应当设置成Disabled。
数据窗口是一个单一的封装的对象,当不希望用户输入某一列时,不能将整个数据窗口的属性设成Disabled,而是应当采用其他的方法,一般来讲,有以下三种方式。
首先,将该列的Tab Order设为0,这样用户将无法按Tab键或用鼠标聚焦在该列上。如果采用这一方法,应当将其原有的Tab Order值存储在一个实例变量中,以便在需要时恢复。
其次,将列的Display Only或Protect属性设为True。这两个属性设为True时,可以使该列得以聚焦(只要Tab Order不为0),用户还可以在该列上选中一些文字以及进行水平、垂直滚屏 ,只是这一列的值不能做修改。如果数据库中的某列大篇幅的多行文字只能显示而不能修改时,可以采用这一方法,但应注意该列的Tab Order不能为0,这样可以保留用户在必要时对其中的部分内容进行拷贝的权利。
第三,将该列的Visible属性设为False。这样该列自动将Tab Order设为0而无法聚焦。当将这个属性值再改为True时,Tab Order的值仍能恢复。这一方法的缺点是在改变属性时屏幕会出现闪烁,因此这一方法不能滥用。
将系统出现的错误提示信息尽可能淡化处理是使用户有安全感的重要因素。开发者应当预见到某些可能出现的错误,尽可能避免出现系统缺省的错误信息,因为一方面由于这些信息本身没有汉化,而且过于专业化,用户不易理解;另一方面也容易使用户以为自己操作错误,造成不安全感。例如,用户可能会在输入数据时违反了数据库的约束条件,开发者应当在PowerBuilder发出SQL语句向数据库提交前对此进行必要的有效性检验。当然使用下拉列表框等方法可以实现外键约束。如果用户直接从键盘输入,需在对数据做update之前验证其有效性。数据库中有些列有非空的约束,如果用户对某些列还没有填入值时就提交数据库也会返回错误,因此开发者在设计窗口时,应对数据库的非空约束等条件先做一预览,不要让从DBMS 发出的错误信息直接显示给用户。另外,在使用数据窗口前,应确保每一列都在Update选项中被选中(在数据窗口画笔菜单的Rows│Update中),否则系统在数据窗口做Update和Insert操作时,将不包括该列。
PowerBuilder中,数据窗口画笔里列的Required Field属性是一个界面很不友好的属性。一旦聚焦在该列上,用户没有输入任何内容就离开或者提交数据窗口时该列没有值,系统都不允许。用户即使不知该输入什么,只是想查询一下其他窗口时, 也要先在该列中写入一些内容,才能关闭这个窗口,因此建议一般不采用这一属性,而是要通过编程来做检查,可以把这段代码放在UpdateStart事件中,这一事件在执行Update()函数时触发。
在用户要做出不易恢复的操作前,应对用户做适当的提示,这样用户在打算探索系统新功能时没有后顾之忧。例如,用户不经意删除一些记录后要恢复它们是困难的,因此在用户删除前,弹出一个窗口提示 “您将删除下列记录,是否继续?”等。在用户修改了记录却没有存盘就退出之前,应用程序应在CloseQuery事件中提示“是否要保存?”等信息。
以上是在应用程序设计的全过程中,应遵循的安全性因素,只有记住这些重要因素,才能在使用该应用时少产生错误,减小维护的压力。这些注意事项概括起来有:
l 统一的外观;
l 引用对象前的有效性检验;
l 使用正确的数据窗口列名;
l 使用适当的GUI控件来使得用户输入有效;
l 需要时对数据窗口的列做保护;
l 提交前对数据窗口列做约束检验;
l 避免用户进入危险地带;
对用户不经意的操作做出提示。