VFP 8:新的错误处理机制
VFP 8:新的错误处理机制
--------------------------------------------------------------------------------
作者 Antonio Casta
译者 RMH
=================
介绍
=================
一种编程语言或软件开发工具的一个最重要的功能是能够提供正确处理错误的机制.
一个好的错误处理将使得开发时间缩短并简单化代码编写. 一个好的错误处理策略是区别高级的专业开发与业余爱好者的因素之一.
我个人认为, 在该新版本的 Visual FoxPro 中的一个最重要的改进是可以进行结构化错误处理.
除该机制自己提供的好处外, 它也把 Visual FoxPro 放入到 .NET 框架及其所有编程语言错误处理策略同步的地位.
该功能通过以下命令来实现:
TRY
CATCH
FINALLY
=================
在发生错误时做什么
=================
直到目前为止, Visual FoxPro 依赖于继承于 xBase(以及一些早期语言的) 经典的错误处理管理:
面对各种可以发生错误的场合, 该技术是, 在执行了一个给定的语句后, 分析 (或测试) 可能的操作结果. 这是转换成一个长的 IF...ELSE...ENDIF 指令串, 插入并散布在我们的代码中.
这种强烈的地使用 IF 语句会产生代码混淆, 难于阅读和维护. 而且这种情况使得应用程序的复杂性成指数级地增长.
要避免 IF 的繁殖, 并处理可能产生的不能预料的事件并中断程序的执行, 一种手段是在代码中包含一个 ON ERROR DO HandleError() 语句, 及其相应的 HandleError() 例程; 该例程将是一个可以检测错误类型并使程序在调后可以继续运行的过程.
随着 Visual FoxPro 3 的出现, 该错误处理可能达到 "对象级", 通过使用 Error 方法,允许封装一个错误处理管理器到一个特定的类中.
这些技术通常称为 "代码隔离": 可能产生错误的代码块被隔离开, 并且错误管理通常是 "本地地" 执行. 这允许通过代码减少和分散 IF 语句的数量.
这些错误处理技术在多数情况下是适当的, 但是一但我们进入到一个每样东西都是组件, 而且组件必须正确地面对它们可以使用的每一种场合的开发模式时, 该技术就不够了. 或者说至少, 它要求数量巨大的额外代码来达到相同的目标和结果.
在一个基于组件的软件开发场景中, 错误处理策略必须达到和具有一系列的目标和特性:
它必须允许一个适当的执行流控制: 意思是面对一个错误条件, 它必须允许我们适当地处理那些执行必须中断
和其它一些情形, 和不知原因的, 执行一个 "复盖" 操作的继续.
执行绝不停止, 其它组件可以因我们的影响而与我们交互.
它可以允许适当通讯关于与错误相关的种类和信息, 因此其它组件可以因为错误的发生而起反应.
关系到前面的问题, 它可以允许适当的传送错误信息. 意思是它应该提供一些机制来促进 "错误传递" 到执行链上. 许多时间错误发生在一个被另一个组件调用的组件中, 它自己被另一个调用, 等等. 有时候仅一可行的选择是报告希望的动作不能完成, 但是能够得到引起错误的组件的信息是重要的. 这将允许向用户提供有意义的信息, 而且同时, 也使错误的诊断和修正更为容易.
要达到所有这些目标, 使用新的异常处理实现起来是非常容易的.
我们只是公正地提及有比老式的方式更灵活的方法存在, 没有免除开发者适当地设计和实现体系, 包括所有的错误处理的相关材料. 而且这样也没有免除他的一般的编程责任. 也就是说, 对于成功的异常处理策略, 要求开发者总是按照前面定义的标准始终如一地使用它.
=================
结构化异常处理
=================
这种异常处理机制是按许多软件开发模式实现的, 如象 C++, Java, 而且从现在开始, 所有的 .Net 语言如 C# 和 VB.Net, 将使用更好的和更有效的错误管理方式. 基本的方法是:
每次发生错误时, 一个异常被创建并 "抛出".
以处理存在的错误, 或 "监视" 该异常.
要实现这一点, 使用一个 TRY ... CATCH ... FINALLY 块. 可能产生错误的代码被 TRY 子句隔离, 并且当错误实际发生时, 执行控制转到 CATCH 子句. 可选的子句 FINALLY 无论错误是否出现都要执行.
完整的语法是:
TRY
[ tryCommands ]
[ CATCH [ TO VarName ] [ WHEN lExpression ]
[ catchCommands ]]
[ FINALLY
[ finallyCommands ]]
ENDTRY
一但程序运行到块的开始处 (TRY), 如果代码无错误地完成了, 流继续到代码中的 FINALLY 子句. 如果没有错误就不执行 CATCH 命令.
如果错误发生了, Visual FoxPro 分析块中的 CATCH 命令. 以一种类似于处理 DO CASE... 结构的方式, 每一个 lExpression 定义包含在 CATCH 命令的 WHEN 部分必须等值为一个逻辑值. 如果找到与产生的异常 (lExpression 是 .T.) 匹配的 CATCH 命令, 则相应组内的代码行被执行.
最后, 执行 FINALLY 子句中的代码. 意思是没有 CATCH 命令被求值. 即使没有需要处理的异常或 CATCH 段中没有求值为 .T. 的表达式, FINALLY 块也会被执行.
一个 EXIT 命令可以放到任何 CATCH 块或 FINALLY 块中.只要在 CATCH 块中找到 EXIT, 执行就从 FINALLY 块继续; 如果在 FINALLY 块中找到它, 则执行转到 ENTRY 语句后.
Si el error ocurre dentro de un m閠odo de un objeto que es llamado dentro de un bloque TRY, Visual FoxPro respeta el procedimiento de error de ese objeto (es decir, ejecuta su m閠odo Error). Esto permite mantener el principio de encapsulamiento de los componentes. Si no existe m閠odo Error, entonces la instrucci髇 CATCH correspondiente es ejecutada.
可能有一个没有任何条件的 CATCH 命令. 在这种情况下, 它相当于 CATCH WHEN .T. 这用在所有可能的条件在一个代码块中处理的场合.
到目前为止看来它与 DO CASE... 或一组 IF 没有太大的区别, 可能写得更好一些. 但这是真正有趣的东西的开始: 每一次在 TRY ... CATCH ... FINALLY 块中发生错误时, Visual FoxPro 从 Exception 类创建一个对象实例.
如果在 CATCH 语句中的任何表达式的值为 True (.T.), Visual FoxPro 对 <>TO VarName 子句中指定的变量赋值到一个真正的对象引用.
该变量的作用域取决于它先前是如何定义的. 如果它还没有被定义, 它被创建为么有变量.
让我们看看我们可以设想的简单的示例:
TRY
USE NonExistent
CATCH TO oExp
SUSPEND
FINALLY
* 未发生什么
ENDTRY
如果我们执行以上代码, 一但挂起程序, 我们可以从命令窗口中检查 Visual FoxPro 创建的 oExp 对象.
一个理解该机制的基本元素是理解和考虑 TRY ... CATCH ... FINALLY 结构可以嵌套. 事实上, 作为相互调用的组件, 这种情况经常发生的. 而且这自然是允许我们传递有意义的信息的方法.