错误处理规范错误处理规范〇、概念澄清概念解释错误是指:导致系统不能按照用户意图工作的一切原因、事件 不是
错误处理规范
错误处理规范〇、概念澄清概念解释错误是指:导致系统不能按照用户意图工作的一切原因、事件 不是指:java.lang.Error及其子类 异常是指:特定编程语言、开发平台提供的一种错误表现机制 不是指但包括:java.lang.Error及其子类,java.lang.Exception及其子类,System.Exception及其子类 ,std::exception及其子类 一、整体规范
按照错误类型,通常的处理方式如下:
错误类型范围处理方式操作员错误与人机界面交互时不满足输入规则、输入范围等发生的错误校验用户输入 提示正确规则 强制其改正 运行时错误与外部资源交互时发生的错误,如网络、文件系统、数据库、其它业务应用系统等记录并抛出异常 其它详见“异常处理规范” 程序员错误与客户模块交互时不满足前置条件后置条件发生的错误,如类库被其他程序员调用时参数超出范围等使用断言
按照调用类型,通常的处理方式如下:
调用类型处理方式同步调用对有能力处理的异常,捕获并处理之 对原始信息过于技术化的异常,捕获并包装之,重新抛出 在调用的中间层,对未知异常保持沉默 在调用的最高层,必须捕获所有异常,避免本身进程或宿主进程崩溃 其它详见“异常处理规范” 异步调用异步调用一般不应有任何返回值 服务方最好以同样的方式返回正常信息和错误信息,即正常信息是通过通知的方式返回的话,错误信息也应该通过通知的方式返回;正常信息是通过主动查询得到的话,错误信息也应该通过主动查询得到
按照展现方式,通常的分类如下:
展现方式涉及模块界面提示只有表示层需要显示界面提示 表示层必须捕获所有错误,避免本身进程或宿主进程崩溃 记录日志除“人机交互界面的输入验证模块”、“xxx模块”外所有模块都应记录错误日志 二、异常处理规范
原则
异常应该是分层的 异常应该集中处理
异常定义
每个模块应该有自己的应用程序异常类型层次,从本模块主动抛出的应用程序异常都应该属于该异常类型层次,客户代码可以只捕捉该层次的基类(?) 应用程序的所有自定义异常都应该从开发平台提供的“应用程序异常基类”派生 中间件等平台程序的运行时异常都应该从开发平台提供的“运行时异常基类”派生(?) 中间件等平台程序的运行时错误都应该从开发平台提供的“错误基类”派生(?)
异常捕获
对有能力处理的异常,捕获并处理之 在调用的中间层,对未知异常保持沉默 在调用的最高层,必须捕获所有异常,避免本身进程或宿主进程崩溃 记录捕获到的每个原始异常的信息
异常抛出
每个模块应使用本模块所能得知的最精确的错误原因报告异常信息 如果有原始异常,在重新抛出的自定义异常中附加原始异常的信息 三、几点说明
错误处理与日志系统
错误处理不等同于日志系统,日志系统只是错误信息的一种记录手段 错误信息的输出应全部调用日志系统来完成
程序员错误与运行时错误
接口函数的前置条件,应该是一种规范,是客户程序员必须遵守的约定;客户程序员违反了约定,程序将产生异常或不可预知的错误;对于这类约定,不应该需要有运行时的代码检查 ;比如如果你的接口函数的一个参数不能为null,而你在函数开始部分程序里写:
if(xxx == null){
throw new someException();
}
你的代码实际上允许该参数为null,因为你对null的情况进行了运行时处理;尽管你在文档里声明该参数不能为null,但如果客户程序员遵守了约定,那么你这段检查代码就是冗余的
当你对参数没有任何检查就进行了使用,而非法的参数值导致了错误,此时有两种情况: 如果你在接口函数说明里列出了参数不允许的非法取值,那么客户程序员应该修改程序避免传入非法值,该类错误称为程序员错误;如果你没有说明,那么你应该修改函数,处理非法参数 不是所有的限制条件在文档里说明一下,就可以把责任扔给客户程序员了,有一些错误必须处理:特别是客户程序员不需要import你的package就可以和你的接口交互的情况,如socket服务器 ,你必须在socket服务程序内部检查所有接收到的数据,拒绝错误的请求,否则极易遭到攻击
错误代码与异常
不应该使用bool值来返回成功与否,bool返回值只应用在真正查询bool状态的操作中,如 bool IsDirty(),bool hasNext()等 整形或bool型的错误代码返回值强迫客户程序员检查每一次调用,应用异常取代之 四、附录
Anders Hejlsberg谈C#异常设计
译者注:在写一段程序时,如果没有用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
所以,你可能很重视这些问题,但是在我们决定是否将Checked Exceptions的一些机制放入C#时,却是颇费了一番思量的。当然,知道什么异常可能在程序中抛出还是有相当价值的,有一些工具也可以作这方面的检查。我不认为我们可以建立一套足够严格而严谨的规则(来完成异常检查),因为(异常)还可能是编译器的错误引起的呢。但是我认为可以在(程序)分析工具上下些功夫,检测是否有可疑代码,是否有未捕获的异常,并将这些隐藏的漏洞给你指出来