not a valid number. "
Response.Flush
Resonse.End
Else
' OK to conver the string value and use it
curSalesTotal = CCur(strSalesTotal)
End If
在JScript中,所有的变量都是对象,并且有typeOf()方法。可以使用typeOf()来确定存在变量中的数据是什么类型,见第3章中的详细论述。
也可以对“null”(VBScript中为Null)进行测试保证在程序使用各种变量之前它们已经赋了值。一个特例是从数据库中获得数据时,数据库中的字段内容经常是Null,表示没有数据。
4. 变量命名和编码约定
阅读过本章和前面几章后,读者可以看出我们对变量名使用三个字母的前缀,用以指明它所代表的数据类型。尽管在这两种脚本语言中用ASP提供的所有变量都是Variant(或JScript中的等价物)类型的,但用变量名来区分出存储在其中的数据的类型仍是非常有用的,有助于防止编写程序时出错。
有许多不同的变量命约定,经常使用的见表7-2:
表7-2 变量类型及前缀
变量类型
前 缀
布尔型(Boolean)
bln
字节型(Byte)
byt
日期/时间型(Date/Time)
dat或dtm
集合型(Collection)
col
双精度型(Double)
dbl
整型(Integer)
int
长整型(Long)
lng
对象型(Object)
obj
单精度型(Single)
sng
字符型(string)
str
对于一个包含函数和子程序的网页,指出某个变量是否已经声明或存在于任何函数和子程序之外是非常有用的。若已经声明,则该变量对网页来说是全局变量。对全局变量加上“g”前缀,所以一全局字符串变量可能被命名为gstrMystring;类似的,以“a”为前缀的变量是数组或数组元素。
程序注释
许多编程人员感觉到对程序增加注释不仅增加了不必要的开发时间,而且也减缓了网页的运行速度,因为脚本解释器每次必须先读整个程序,然后再跳过这些注释。尽管这种观点有一定的道理,但是一个月后再回过头来想读懂没有注释的程序,是非常困难的。
至少应该对常用函数和子程序进行注释以便你和其他人能重新使用这些程序。特别是,使用新的Server.Execute方法更加容易(详细情况参阅第4章)。下面是微软提供的一个例程的注释格式。
'*****************************************************
'Purpose: what the routine is designed to achieve
'Inputs: a list of all the parameters to the routine
' parameter1: description, data-type, etc.
' parameter2: description, data-type, etc.
'Returns: what data type is returned, and what it contains
'Comments: other comments about the routine, update history, etc.
'*****************************************************
5. 封装脚本语言以便代码重用
刚刚看到了如何注释子程序和函数以便易于重新使用。面向对象编程的原理是建立在程序代码重用的基础上的,并且SSI的#include和新的Server.Execute方法使调用存储在程序库中的函数更容易。
例如,如果有一系列函数用于计算税收和商品的应付费用。可把包含这段程序的页面插入其他页面中:
<!-- #inculde VIRTUAL="/library/code/online_sales/tax_and_delivery.inc" -->
包含文件必须含有脚本定界符,或者用<SCRIPT RUNAT="SERVER">...</SCRIPT>或者用<%...%>,每一个子程序和函数应该采用其要求的数值做参数,并且用函数值或更新的参数返回结果。不能使用全局变量,况且不同网页之间的全局变量也是不可用的。但在主网页中的程序能安全地调用所需的函数和子程序。
另外可使用Server.Execute(或者Server.Transfer)把执行转到另一个网页。如果有一段ASP代码用来为客户创建在线采购一览表,这种方法是非常有用的。它包含HTML用来创建标题、表格,用代码进行计算并用Request集合的内容填写相应值(记住不能使用Server.Execute或Server.Transfer把脚本变量传到另一个网页)。另外,运行的网页能够支持函数、类定义(在VBScript中),或者其他设计为可重新使用的内容。
6. 注意潜在的错误情况
编程时不管如何仔细,比如在使用和对变量类型转换之前对变量值进行测试,但总还是有一些情况不能避免错误的出现。明显的例子是:当使用FileSystemObject对象的方法设法访问一个用户指定的文件时,不能确定这个文件是否已移动、删除或者标记成只读型,所有这些操作都可能使程序不能工作。
其他类似的情况可能是,当访问数据库或其他数据存储时,对用户帐户而言,有时要求某一层权限。在这种情况下,可能因为需要的访问不能实现,使程序不能工作。
可以通过采取预防性措施编写程序,来测试类似的潜在错误。例如,可以使用Tools组件或者FileSystemObject对象的FileExists方法来查看,是否一个文件在访问之前就已存在了;或者使用Permission Checker组件来查看当前用户帐号是否有访问需要的文件或资源的权限;也可以通过使用FileSystemObject获得一个文件的属性设置,以便在删除或重写之前查看文件是否是只读的。
如果不考虑可能发生的错误并防止错误发生的话,这些情况和许多类似的情况都可能是潜在的运行期错误源。
7. 最后的测试
很明显,测试是对错误的最好防范方法。错误能通过应用程序影响到其他操作,如果不及时发现能引起不可估量的损失。用各种数值(如用户提交的,或者访问一个数据库得到的数据)对网页进行测试。同时,更重要的是,如果采用我们不希望的值会发生什么。程序能避免这些情况产生其他错误或者避免扰乱正在测试的子程序吗?
好的测试技术应该包括一系列值,如期望的值、边界条件值和超出边界的值。用期望传送到网页的值进行测试是应该经常做的工作,同样超出边界的值通常比较容易阻止。例如,可以限制可接受的数值范围为-100~+100,程序如下:
If (intValue < -100) or (intValue > 100) Then
' not a valid value, so report an error and stop
Response.Write "Value must be between ?100 and +100 inclusive. "
Response.Flush
Response.End
End If
然而要记住查看边界条件,上面的程序能处理-100和+100吗?想把数据限制在-100~+100中吗?取0时会发生什么?上面的程序会显示“Divide By Zero”错误而最终停止执行吗?
7.4 处理错误
即使采用了防御性编程技术之后,错误仍能进入到网页,这可能是因为测试并不充分,或者是因为所依靠的一些其他资源或服务没有正确工作。为了防止页面出现问题,在程序中要能够进行定制错误处理。
7.4.1 ASP缺省错误处理器
前面已经看到过,ASP和IIS能找出网页中的大多数错误,并且能自动生成错误信息页,这些错误几乎总是500.100类型的,并且IIS用Server.Transfer方法装载以500-100.asp命名的缺省错误页,然后传送给客户。第4章介绍了这一工作过程,以及如何与定制错误网页接口。
然而,运行期脚本错误不总是由IIS发现的,当一个运行期错误发生时,脚本引擎会查看一下目前执行点或语句的环境。如果正在执行一个子程序或函数,缺省的脚本引擎错误处理器通过终止子程序的运行并返回调用子程序的地方来指出错误。
在这里,程序会查看是否实现了其他的错误处理器,如果没有的话,又会重复这个过程,然后返回到调用子程序的地方。当子程序返回到网页的主程序(在任何其他子程序或函数外面)时,程序又查看是否实现了任何其他的错误处理器。在这个过程中,只有确实没有发现其他的错误处理器,程序才给ASP提示错误,指示IIS把执行转到缺省的错误页面。
Response.Flush
Resonse.End
Else
' OK to conver the string value and use it
curSalesTotal = CCur(strSalesTotal)
End If
在JScript中,所有的变量都是对象,并且有typeOf()方法。可以使用typeOf()来确定存在变量中的数据是什么类型,见第3章中的详细论述。
也可以对“null”(VBScript中为Null)进行测试保证在程序使用各种变量之前它们已经赋了值。一个特例是从数据库中获得数据时,数据库中的字段内容经常是Null,表示没有数据。
4. 变量命名和编码约定
阅读过本章和前面几章后,读者可以看出我们对变量名使用三个字母的前缀,用以指明它所代表的数据类型。尽管在这两种脚本语言中用ASP提供的所有变量都是Variant(或JScript中的等价物)类型的,但用变量名来区分出存储在其中的数据的类型仍是非常有用的,有助于防止编写程序时出错。
有许多不同的变量命约定,经常使用的见表7-2:
表7-2 变量类型及前缀
变量类型
前 缀
布尔型(Boolean)
bln
字节型(Byte)
byt
日期/时间型(Date/Time)
dat或dtm
集合型(Collection)
col
双精度型(Double)
dbl
整型(Integer)
int
长整型(Long)
lng
对象型(Object)
obj
单精度型(Single)
sng
字符型(string)
str
对于一个包含函数和子程序的网页,指出某个变量是否已经声明或存在于任何函数和子程序之外是非常有用的。若已经声明,则该变量对网页来说是全局变量。对全局变量加上“g”前缀,所以一全局字符串变量可能被命名为gstrMystring;类似的,以“a”为前缀的变量是数组或数组元素。
程序注释
许多编程人员感觉到对程序增加注释不仅增加了不必要的开发时间,而且也减缓了网页的运行速度,因为脚本解释器每次必须先读整个程序,然后再跳过这些注释。尽管这种观点有一定的道理,但是一个月后再回过头来想读懂没有注释的程序,是非常困难的。
至少应该对常用函数和子程序进行注释以便你和其他人能重新使用这些程序。特别是,使用新的Server.Execute方法更加容易(详细情况参阅第4章)。下面是微软提供的一个例程的注释格式。
'*****************************************************
'Purpose: what the routine is designed to achieve
'Inputs: a list of all the parameters to the routine
' parameter1: description, data-type, etc.
' parameter2: description, data-type, etc.
'Returns: what data type is returned, and what it contains
'Comments: other comments about the routine, update history, etc.
'*****************************************************
5. 封装脚本语言以便代码重用
刚刚看到了如何注释子程序和函数以便易于重新使用。面向对象编程的原理是建立在程序代码重用的基础上的,并且SSI的#include和新的Server.Execute方法使调用存储在程序库中的函数更容易。
例如,如果有一系列函数用于计算税收和商品的应付费用。可把包含这段程序的页面插入其他页面中:
<!-- #inculde VIRTUAL="/library/code/online_sales/tax_and_delivery.inc" -->
包含文件必须含有脚本定界符,或者用<SCRIPT RUNAT="SERVER">...</SCRIPT>或者用<%...%>,每一个子程序和函数应该采用其要求的数值做参数,并且用函数值或更新的参数返回结果。不能使用全局变量,况且不同网页之间的全局变量也是不可用的。但在主网页中的程序能安全地调用所需的函数和子程序。
另外可使用Server.Execute(或者Server.Transfer)把执行转到另一个网页。如果有一段ASP代码用来为客户创建在线采购一览表,这种方法是非常有用的。它包含HTML用来创建标题、表格,用代码进行计算并用Request集合的内容填写相应值(记住不能使用Server.Execute或Server.Transfer把脚本变量传到另一个网页)。另外,运行的网页能够支持函数、类定义(在VBScript中),或者其他设计为可重新使用的内容。
6. 注意潜在的错误情况
编程时不管如何仔细,比如在使用和对变量类型转换之前对变量值进行测试,但总还是有一些情况不能避免错误的出现。明显的例子是:当使用FileSystemObject对象的方法设法访问一个用户指定的文件时,不能确定这个文件是否已移动、删除或者标记成只读型,所有这些操作都可能使程序不能工作。
其他类似的情况可能是,当访问数据库或其他数据存储时,对用户帐户而言,有时要求某一层权限。在这种情况下,可能因为需要的访问不能实现,使程序不能工作。
可以通过采取预防性措施编写程序,来测试类似的潜在错误。例如,可以使用Tools组件或者FileSystemObject对象的FileExists方法来查看,是否一个文件在访问之前就已存在了;或者使用Permission Checker组件来查看当前用户帐号是否有访问需要的文件或资源的权限;也可以通过使用FileSystemObject获得一个文件的属性设置,以便在删除或重写之前查看文件是否是只读的。
如果不考虑可能发生的错误并防止错误发生的话,这些情况和许多类似的情况都可能是潜在的运行期错误源。
7. 最后的测试
很明显,测试是对错误的最好防范方法。错误能通过应用程序影响到其他操作,如果不及时发现能引起不可估量的损失。用各种数值(如用户提交的,或者访问一个数据库得到的数据)对网页进行测试。同时,更重要的是,如果采用我们不希望的值会发生什么。程序能避免这些情况产生其他错误或者避免扰乱正在测试的子程序吗?
好的测试技术应该包括一系列值,如期望的值、边界条件值和超出边界的值。用期望传送到网页的值进行测试是应该经常做的工作,同样超出边界的值通常比较容易阻止。例如,可以限制可接受的数值范围为-100~+100,程序如下:
If (intValue < -100) or (intValue > 100) Then
' not a valid value, so report an error and stop
Response.Write "Value must be between ?100 and +100 inclusive. "
Response.Flush
Response.End
End If
然而要记住查看边界条件,上面的程序能处理-100和+100吗?想把数据限制在-100~+100中吗?取0时会发生什么?上面的程序会显示“Divide By Zero”错误而最终停止执行吗?
7.4 处理错误
即使采用了防御性编程技术之后,错误仍能进入到网页,这可能是因为测试并不充分,或者是因为所依靠的一些其他资源或服务没有正确工作。为了防止页面出现问题,在程序中要能够进行定制错误处理。
7.4.1 ASP缺省错误处理器
前面已经看到过,ASP和IIS能找出网页中的大多数错误,并且能自动生成错误信息页,这些错误几乎总是500.100类型的,并且IIS用Server.Transfer方法装载以500-100.asp命名的缺省错误页,然后传送给客户。第4章介绍了这一工作过程,以及如何与定制错误网页接口。
然而,运行期脚本错误不总是由IIS发现的,当一个运行期错误发生时,脚本引擎会查看一下目前执行点或语句的环境。如果正在执行一个子程序或函数,缺省的脚本引擎错误处理器通过终止子程序的运行并返回调用子程序的地方来指出错误。
在这里,程序会查看是否实现了其他的错误处理器,如果没有的话,又会重复这个过程,然后返回到调用子程序的地方。当子程序返回到网页的主程序(在任何其他子程序或函数外面)时,程序又查看是否实现了任何其他的错误处理器。在这个过程中,只有确实没有发现其他的错误处理器,程序才给ASP提示错误,指示IIS把执行转到缺省的错误页面。