当前位置 : 主页 > 编程语言 > c语言 >

关于程序异常

来源:互联网 收集:自由互联 发布时间:2023-09-06
一、整体规范 按照错误类型,通常的处理方式如下: 错误类型 范围 处理方式 操作员错误 与人机界面交互时不满足输入规则、输入范围等发生的错误 校验用户输入 提示正确规则 强制


一、整体规范

  1. 按照错误类型,通常的处理方式如下:

错误类型

范围

处理方式

操作员错误

与人机界面交互时不满足输入规则、输入范围等发生的错误

  • 校验用户输入
  • 提示正确规则
  • 强制其改正

运行时错误

与外部资源交互时发生的错误,如网络、文件系统、数据库、其它业务应用系统等

  • 记录并抛出异常
  • 其它详见“异常处理规范”

程序员错误

与客户模块交互时不满足前置条件后置条件发生的错误,如类库被其他程序员调用时参数超出范围等

  • 使用断言
  1. 按照调用类型,通常的处理方式如下:

调用类型

处理方式

同步调用

  • 对有能力处理的异常,捕获并处理之
  • 对原始信息过于技术化的异常,捕获并包装之,重新抛出
  • 在调用的中间层,对未知异常保持沉默
  • 在调用的最高层,必须捕获所有异常,避免本身进程或宿主进程崩溃
  • 其它详见“异常处理规范”

异步调用

  • 异步调用一般不应有任何返回值
  • 服务方最好以同样的方式返回正常信息和错误信息,即正常信息是通过通知的方式返回的话,错误信息也应该通过通知的方式返回;正常信息是通过主动查询得到的话,错误信息也应该通过主动查询得到

二、异常处理规范

异常应该是分层的

异常定义

  • 每个模块应该有自己的应用程序异常类型层次,从本模块主动抛出的应用程序异常都应该属于该异常类型层次,客户代码可以只捕捉该层次的基类(?)
  • 应用程序的所有自定义异常都应该从开发平台提供的“应用程序异常基类”派生
  • 中间件等平台程序的运行时异常都应该从开发平台提供的“运行时异常基类”派生(?)
  • 中间件等平台程序的运行时错误都应该从开发平台提供的“错误基类”派生(?)

异常捕获

  • 对有能力处理的异常,捕获并处理之
  • 在调用的中间层,对未知异常保持沉默
  • 在调用的最高层,必须捕获所有异常,避免本身进程或宿主进程崩溃
  • 记录捕获到的每个原始异常的信息

异常抛出

  • 每个模块应使用本模块所能得知的最精确的错误原因报告异常信息
  • 如果有原始异常,在重新抛出的自定义异常中附加原始异常的信息

三、几点说明

错误处理与日志系统

  • 错误处理不等同于日志系统,日志系统只是错误信息的一种记录手段
  • 错误信息的输出应全部调用日志系统来完成

程序员错误与运行时错误

  • 接口函数的前置条件,应该是一种规范,是客户程序员必须遵守的约定;客户程序员违反了约定,程序将产生异常或不可预知的错误;对于这类约定,不应该需要有运行时的代码检查 ;比如如果你的接口函数的一个参数不能为null,而你在函数开始部分程序里写:

if (xxx == null

throw new

}

你的代码实际上允许该参数为null,因为你对null的情况进行了运行时

  • 当你对参数没有任何检查就进行了使用,而非法的参数值导致了错误,此时有两种情况: 如果你在接口函数说明里列出了参数不允许的非法取值,那么客户程序员应该修改程序避免传入非法值,该类错误称为程序员错误;如果你没有说明,那么你应该修改函数,处理非法参数
  • 不 是所有的限制条件在文档里说明一下,就可以把责任扔给客户程序员了,有一些错误必须处理:特别是客户程序员不需要import你的package就可以和 你的接口交互的情况,如socket服务器 ,你必须在socket服务程序内部检查所有接收到的数据,拒绝错误的请求,否则极易遭到攻击

错误代码与异常

  • 不应该使用bool值来返回成功与否,bool返回值只应用在真正查询bool状态的操作中,如 bool IsDirty (),bool hasNext
  • 整形或bool型的错误代码返回值强迫客户程序员检查每一次调用,应用异常取代之

四、附录

Anders Hejlsberg谈C#异常设计

  • 对 Checked Exceptions

 

(译者注:在写一段程序时,如果没有用 try-catch 捕捉异常或者显式的抛出异常,而希望程序自动抛出,一些语言的编译器不会允许编译通过,如 Java 就是这样。这就是 Checked Exceptions 最基本的意思。该特性的目的是保证程序的安全性和健壮性。 Zee&Snakey(MVP) 对此有一段很形象的话,可以参见: http : //www.blogcn.com/user2/zee/main.asp 。 Bruce Eckel 也有相关的一篇文章(《 Does Java need Checked Exceptions 》),参见: http : //www.mindview.net/Etc/Discussions/CheckedExceptions

Bruce Eckel : C# 没有 Checked Exceptions ,你是怎么决定是否在 C# 中放置这种特性的么?

Anders Hejlsberg :我发现 Checked Exceptions 在两个方面有比较大的问题:扩展性和版本控制。我知道你也写了一些关于 Checked Exceptions

Bruce Eckel :我一直认为 Checked Exceptions

Anders Hejlsberg :是的,老实说,它看起来的确相当重要,这个观点并没有错。我也十分赞许 Checked Exceptions 特性的美妙。但它某些方面的实现会带来一些问题。例如,从 Java 中 Checked Exceptions 的实现途径来看,我认为它在解决一系列既有问题的同时,付出了带来一系列新问题的代价。这样一来,我就搞不清楚 Checked Exceptions

Bruce Eckel : C# 设计小组对 Checked Exceptions

Anders Hejlsberg :不,在这个问题上,我们有着广泛的共识。 C# 目前在 Checked Exceptions

假 设你让一个新手去编一个日历控件,他们通常会这样想:“哦,我会写出世界上最好的日历控件!我要让它有各种各样的日历外观。它有显示部分,有这个,有那 个……”他们将所有这些构想都放到控件中去,然后花两天时间写了一个很蹩脚的日历程序。他们想:“在程序的下一个版本中,我将实现更多更好的功能。”

但 是,一旦他们开始考虑如何将脑海中那么多抽象的念头具体实现出来时,就会发现他们原来的设计是完全错误的。现在,他们正蹲在一个角落里痛苦万状呢,他们发 现必须将原来的设计全盘抛弃。这种情况我不是看到一次两次了。我是一个最低纲领主义者。对于影响全局的问题,在没有实际解决方案前,千万不要将它带入到整 个框架中去,否则你将不知道这个框架在将来会变成什么样子 。

Bruce Eckel :极限编程(The Extreme Programmers)上说:“用最简单的办法来完成工作。”

Anders Hejlsberg :对呀,爱因斯坦也说过:“尽可能简单行事。”对于Checked Excpetions特性,我最关心的是它可能给程序员带来哪些问题。试想一下,当程序员调用一些新编写的有自己特定的异常抛出句法的API时,程序将变 得多么纷乱和冗长。这时候你会明白Checked Exceptions不是在帮助程序员,反而是在添麻烦。正确的做法是,API的设计者告诉你如何去处理异常而不是让你自己想破脑袋。

 

  • Checked Exceptions的版本相关性

 

Bill Venners :你提到过 Checked Exceptions的扩展性和版本相关性这两个问题。现在能具体解释一下它们的意思么?

Anders Hejlsberg :让我首先谈谈版本相关性,这个问题更容易理解。假设我创建了一个方法 foo ,并声明它可能抛出 A 、 B 、 C 三个异常。在新版的 foo 中,我要增加一些功能,由此可能需要抛出异常 D 。这将产生了一个极具破坏性的改变,因为原来调用此方法时几乎不可能处理过 D

    也就是说,在新版本中增加抛出的异常时,给用户的代码带来了破坏。在接口中使用方法时也有类似的问题。一个实现特定功能的接口一经发布,就是不可改变的,新功能只能在新版的接口中增加。换句话说,就是只能创建新的接口。在新版本中,你只有两种选择,要么建立一个新的方法 foo2 , foo2 可以抛出更多的异常,要么在新的 foo 中捕获异常 D ,并转化为原来的异常 A 、 B 或者 C

Bill Venners :但即使在没有 Checked Exceptions特性的语言中,(增加新的异常)不是同样会对程序造成破坏么?假如新版foo抛出了需要用户处理的新的异常,难道仅仅因为用户不希望这个异常发生,他写代码时就可以置之不理吗?

Anders Hejlsberg :不,因为在很多情况下,用户根本就不关心(异常)。他们不会处理任何异常。其实消息循环中存在一个最终的异常处理者,它会显示一个对话框提示你程序运行出错。程序员在任何地方都可以使用 try finally

很多语言的 throws 语法(如 Java ),没必要地强迫你去处理异常,也就是逼迫你搞清楚每一个异常的来源。它们要求你要么捕获声明的异常,要么将它们放入 throws 语句。程序员为了达到这个要求,做了很多荒谬可笑的事情。例如他们在声明每个方法时,都必须加上修饰语:“ throws Exception

Bill Venners :如此说来,你认为不要求程序员明确的处理每个异常的做法,在现实中要适用得多了?

Anders Hejlsberg :人们为什么认为(显式的)异常处理非常重要呢?这太可笑了。它根本就不重要。在我印象中,一个写得非常好的程序里, try finally 和 try catch 语句数目大概是 10 : 1 。在 C# 中,也可以使用和类似 try finally 的 using

Bill Venners : finally

Anders Hejlsberg : finally 保 证你不被异常干扰,但它不直接处理异常。异常处理应该放在别的什么地方。实际上,在任何一个事件驱动的(如现代图形界面)程序中,在主消息循环里,都有一 个缺省的异常处理过程,程序员只需要处理那些没被缺省处理的异常。但你必须确保任何异常情况下,原来分配的资源都能被销毁。这样一来,你的程序就是可持续 运行的。你肯定不希望写程序时,在 100

 

  • Checked Exceptions

 

Bill Venners :那么 Checked Exceptions

Anders Hejlsberg 扩展性有时候和版本性是相关的。 在一个小程序里, Checked Exceptions 显得蛮迷人的。你可以捕捉 FileNotFoundException 异常并显示出来,是不是很有趣?这在调用单个的 API 时也挺美妙的。但是在开发大系统时,灾难就降临了。你计划包含 4 、 5 个子系统,每个子系统抛出 4 到 10 个异常。但是(实际开发时),你每在系统集成的梯子上爬一级,必须被处理的新异常都将呈指数增长。最后,可能每个子系统需要抛出 40 个异常。将两个子系统集成时,你将必须写 80 个 throw

很多时候, Checked Exceptions 都会激怒程序员,于是程序员就想办法绕过这个特性。他要么在到处都是写“ throws Exception ”,要么——我都不知道自己看到多少回了——写“ try, da da da da da( 译者注:意思是飞快的写一段代码 ), catch curly curly( 译者注:即‘ { } ’ ) ”,然后说:“哦,我会回头来处理这些空的异常处理语句的。”实际上,理所当然的没有任何人会回头干这些事情。这时候, Checked Exceptions

所以,你可能很重视这些问题,但是在我们决定是否将 Checked Exceptions 的一些机制放入 C#

【出处:响水网页制作公司 http://www.1234xp.com/xiangshui.html 复制请保留原URL】
上一篇:为现代 JavaScript 开发做好准备
下一篇:没有了
网友评论