`
sunxboy
  • 浏览: 2869536 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论
阅读更多

<!----><!----><!----> <!---->

异常处理措施

——针对有效的错误处理设计异常管理系统

作者:Jean-Pierre NorguetJavaWorld.com,11/15/07

<!---->1.            <!---->摘要

在面向对象的应用程序中,由于代码重载、错误的问题处理方式,导致异常有越来越多的趋势。在这篇文章中,作者Jean-Pierre Norguet 介绍了如何设计异常,来实现一个简单的、可读的、健壮的、灵活的、面向调试的及用户友好的错误处理系统。在本文中,作者提出了简单异常集合的设计,并且给出了Java 实现的源代码。最后,作者介绍了如何将这样的设计集成到一个Java 的企业应用程序中。

在一个面向对象的项目中,设计异常处理的最好途径从来也没有如我们期待的那样清晰。在旧的大的系统中,异常的发生有激增的趋势,最终达到几百行的代码。对于一些常见的编程场景,异常检查是必须的,但是也会带来可观的处理开销。虽然安静的异常捕获可以找到问题的源头,但是避免不了它的一些缺点(虽然这些缺点不是致命的);比如你必须熟悉这些代码。

<!---->2.            <!---->

本文将介绍如何通过有限的异常集合来满足一个错误处理的需求。在建立起一个好的错误处理系统框架之后,将会指出异常处理设计中常见的错误,这些错误将会逐渐损害应用程序的性能;然后将会给出一个异常集合的例子,这个例子支持本文讨论的异常处理设计的基本功能:异常系统应该被设计成能够帮助外部系统(用户)处理未知情况(在运行时发生),而不是设计成能够帮助编程人员处理已知情况;还会介绍本文给出例子中的各个类的含义以及如何在一个特定的Java 企业应用程序体系中使用它们;最后给出这个例子的Java 实现。

<!---->3.            <!---->错误处理需求

什么是一个好的错误处理系统?抛开审美角度的考虑,一个好的错误处理系统通常要符合下面的条件:

·任何异常都不会导致应用系统的崩溃。

·在发生异常时,允许应用程序进行相应的处理。

·显示给用户的错误信息要清晰的描述发生了什么错误以及应该采取什么样的处理。

·如果需要辅助信息,错误信息还要帮助用户与帮助部门交互,为帮助部门团队提供必要的信息,是他们能够快速的容易的重现错误。

·日志信息能为开发团队人员在识别错误、在应用程序代码中定位错误产生的位置以及修正错误提供必要的信息。

·错误处理代码不会降低应用程序代码的可读性。必要的时候,错误处理仅仅是一个安全网,它对应用程序的核心功能具有较低的反问权限。

一个错误处理系统的设计符合这些条件才能被认为是完整的。对于大多数Java 开发人员来说接下来的问题就是:如何灵活的使用异常类来设计一个错误处理系统,而不是通过简单的重载它们来实现。

<!---->3.1.    <!---->应该避免的常见用法

可以通过一个有限的异常类集合来满足上面提到的需求。当设计这样的一个异常类集合是,你应该避免一些常见的用法,例如:
·对每个问题都定义的异常类,这样会导致系统中异常类的激增。

·对每个包定义一个异常类集合,这没什么用处而且也会导致系统中异常类的激增。

·对每个异常都提供checkednon-checked 两个版本,引入了检测异常开销。异常语义的后序副本也会混淆异常处理的设计。

·最后,抛出和捕获通用异常在很多方面也是错误倾向。

本文下面提到的异常类集合按照错误处理语义分类,避免了异常处理相关的常见问题。尤其是在应用程序的规模和复杂程度增长是,这种方式更值得推荐。

<!---->4.            <!---->异常处理设计

1 展示了异常类集合的设计,这个设计避免了异常类激增、检测异常开销和异常的安静捕获。

<!----><!----> <!---->

1. 一个异常类集合的例子

在这个图中你会发现有些异常是checked ,而有些是runtime 。为了避免异常抛出声明的开销,checked 异常基于下面两个目的被保留下来:

<!---->1、  <!---->告诉调用方法,在这个处理过程中发生了一个可预见的意外情况。在这种情况下,问题的语义已经被处理方法定义了,直接捕获会更好。

<!---->2、  <!---->告诉外部系统发生了一个未解决的问题,需要根据异常语义来处理这个问题。

<!---->4.1.    <!---->理解异常语义

在这里阐明本文对异常语义的定义。在作者看来,设计对象的类需要根据它们在现实世界中的等价物。一个水果或者一个人很容易设计成一个Java 对象类。但是异常设计却不同:因为一个水果或者一个人在现实世界中非常直观,异常却不同。实际上,上面的两类异常中,只有第一类在现实世界中存在;而第二类异常模拟了系统执行过程中会发生什么错误,因此在系统之外就不存在了。直接捕获因此也只对第一类异常适合。

作者的设计建议就是异常应该根据它们的目的来设计。系统内部的、自我调整的异常就意味着是帮助系统来处理不可预见的情况。这些异常的目的也就不是模拟系统中的问题,而是给一个系统需要采取什么措施的指示。

<!---->5.            <!---->一个异常类集合的例子

在图1 中你可以看到四类异常对应四类处理,如下:

<!---->1、  <!---->BusinessException: 一种异常情况发生。这种情况是可预见的,也可以被调用方法检测到并立即采取措施。

<!---->2、  <!---->ParameterException: 输入的数据对处理过程不合法。用户被要求重新输入有效数据或者修改处理过程的条件。

<!---->3、  <!---->TechnicalException: 技术问题,如无效的SQL 语句。这种情况下,请求操作未完成。用户需要和帮助部门联系,调查问题的原因;或者尝试其它的服务。对使用系统的其它用户没有影响。

<!---->4、  <!---->CriticalTechnicalException: 技术问题,如数据库崩溃。在这种情况下整个应用程序都ub 可用。用户被建议稍后重试。在问题修复前,所有的用户都不能使用系统。

这个异常类集合只是一个例子;很多异常类集合都可以参照它来定义。例如,TechnicalExceptionCriticalTechnicalException 可以被设计成一个类,这个类声明一个severity 布尔属性。重要的是关注采取什么处理措施而不是什么问题引起异常。

<!---->5.1.    <!---->异常日志记录

虽然异常语义关注采取的措施,但是出现的问题也很重要。例如,开发团队人员可以使用这些信息调试代码。在异常处理设计中,导致异常的信息能够在以用程序的错误日志中发现。在适当的位置使用一个好的日志记录框架,这个框架能够有效的从异常信息和堆栈跟踪中记录问题信息。

剩下的唯一问题就是怎么样设计异常类使之能够方便的返回信息。一个解决方案就是为异常类声明一个id 属性来代表遇到的问题的种类。另外,问题自身可带有通用异常,也就是把通用异常内嵌到应用程序异常中。在捕获的时候,原始的信息和堆栈跟踪信息能够通过内嵌的异常得到。id 属性和内嵌异常是包装问题的两种途径。

<!---->6.            <!---->异常处理流程的设计

一旦你已经设计好异常类本身了,下一步需要思考的就是它在应用程序中的处理流程。一个标准的JEE 应用程序体系通常包括四个部分:展现、业务、集成、持久。异常经常在集成和持久部分被抛出。在业务部分,里层的捕获checked 异常,而外层捕获runtime 异常并根据它们的类型来采取相应的处理措施。也可以在业务部分抛出一些checked 异常并且捕获它们。在这种模式下,集成和持久部分,包括业务部分的里层都将runtime 异常转化成具体的处理措施。图2 展示的就是一个典型的JEE 应用程序异常处理流程。

<!----><!----> <!---->

2. 标准JEE 包体系中异常的处理流程

异常抛出路径是指从持久部分(假设)发生问题到问题被解决所经历的流程。如果持久层的调用方法能够解决这个问题,那么这个异常就直接被捕获并采取相应的处理措施,业务流程一切照常;如果问题不能被解决,异常将内嵌到一个runtime 异常中经过业务部分的中间层传递到应用程序的上层中,在这里,典型的处理方法就是使用一些应用程序控制器来捕获这些runtime 异常并采取相应的处理措施,展现层显示相应的错误信息给用户。直接捕获checked 异常和推迟捕获runtime 异常是异常处理设计中的两种主要方案,如图3 所示。

<!----><!----> <!---->

3. 直接捕获checked 异常和推迟捕获runtime 异常

<!---->7.            <!---->扩展java.lang.Exception

文中提到的异常处理设计方案在任何的面向对象语言中都可以很容易的实现,包括Java 。一个相似的异常类树已经在标准Java 库中提供了。在这个库中异常被设计为java.lang.Throwableckeched 异常被设计为java.lang.Exceptionruntime 异常被设计为java.lang.RuntimeException

java.lang.Exception 下,有大量泛语义的业务异常。运行时应用程序异常,如ParamterExceptionTechnicalExceptionCriticalTechnicalException (见图1 )各自都设计成相应的概要异常,如IllegalArgumentExceptionMissingResourceExceptionIllegalStateException

在应用程序中,重用Java 标准异常是一个不错的主意,但是由Java 标准类抛出的异常也会导致一些混乱。你可以通过扩展java.lang.Exception 的自定义异常类树来避免这样的混乱。通过自定义的异常类树,你还可以实现内嵌异常和问题ID 。列表1 给出了文中例子的Java 代码实现。注意,它包括内嵌异常和问题ID

列表1. 通过Java 代码实现内嵌异常和问题ID

 

public class NestedException extends RuntimeException {

   protected Exception nestedException;

   protected int issueId;

   public NestedException(String msg, Exception e, int id) {

      super(msg);

      this.nestedException = e;

      this.issueId = id;

   }

   public Exception getNestedException() {

      return this.nestedException;

   }

   public int getIssue() {

      return this.issueId;

   }

}

public interface Issue {

   public final static int UNDEFINED = 0;

   public final static int EXTERNAL_SERVICE_1_DOWN = 1;

   public final static int EXTERNAL_SERVICE_2_DOWN = 2;

   public final static int SQL_STATEMENT_ERROR = 3;

   // ...

} 
 

<!---->8.            <!---->总结

设计一个满足好的错误处理系统需求的异常类树非常简单。简单的秘诀就是将设计的主要精力集中在系统应该采取什么样的处理措施,而不是关注会出现的什么样的问题。在本文的设计当中,问题的信息封装在异常类里面。通过在处理措施和问题之间分配异常语义,让你将异常类树限制在一个有限的异常类集合中(可能就六七个左右)。这种设计不仅限制了异常类激增,洱海保证代码的可读性,使你在以后的开发中以最佳的清晰度来关注应用程序的业务逻辑的编码。

<!---->9.            <!---->作者简介

Jean-Pierre Norguet 拥有布鲁塞尔大学的计算机科学和网络工程博士学位。在IBM 经过了三年全职的电子商务应用程序关键任务的Java 开发后,作为团队领导者和教练,他擅长的技术领域包括了整个应用程序开发周期。目前专注于Java 技术、实体集成和迷你Web 应用的研究。除了一些在线Java 文章外,Norguet 博士还与PrenticeIBM 出版社一起出版了有关JEE 的著作,同时还在ACMIEEESpringer-Verlag 的国际研讨会发表了一些文章。他的业务兴趣还包括艺术绘画、兼职法语教师和临时健康顾问。

<!---->10.          <!---->相关资源

本文中提到的异常类集合的完整代码可在 custom exception set 下载。

其它相关文章

英文原文地址

 

  • 大小: 12 KB
  • 大小: 6.5 KB
  • 大小: 8.6 KB
分享到:
评论

相关推荐

    X3,X3E伺服报警处理方法.pdf

    本文将涵盖报警处理方法的标题、描述、标签和部分内容,并对每个报警代码和名称进行解释和处理措施。 系统报警 Err.001:系统参数异常 原因:控制电源电压瞬时下降;升级驱动器软件之后,部分参数的范围有改动,...

    ( D530 E239模块异常处理指南1

    文档指出,当D530和E239手机的CDMA软件版本为空时,即无法正常显示版本号的情况下,才需要采取异常处理措施。这通常意味着手机的模块功能出现故障,需要通过特定的操作流程来修复。软件版本的查询可以通过输入特殊...

    异常处理.pdf

    通过异常处理,我们可以将正常业务代码和异常处理代码分开,使程序的逻辑更清晰,增强程序的健壮性。 异常机制主要包含以下几个部分: 1. 异常概述:异常是程序在执行过程中发生的不正常情况,比如文件找不到、...

    Oracle 存储过程异常处理.docx

    异常处理是指在程序执行过程中出现错误或异常时,采取相应的处理措施,以确保程序的可靠性和安全性。 一、异常的优点 使用异常处理可以方便地处理错误,并且异常处理程序与正常的事务逻辑分开,提高了可读性。异常...

    delphi线程异常处理

    当然,实际的异常处理可能更为复杂,比如记录错误信息、发送通知或者采取适当的恢复措施。 此外,Delphi提供了`TThread.RaiseException`方法,允许你在线程内部或外部手动引发异常。这对于在多线程环境中同步错误...

    JAVA中异常处理的WORD文档

    通过异常处理,我们可以捕获这些错误,避免程序立即终止,并有机会执行清理操作或采取适当的恢复措施。 2. 异常处理的格式 异常处理通常使用以下格式: ```java try { // 可能出现异常的代码 } catch (异常类1 ...

    Java异常处理终结篇——如何进行Java异常处理设计 - 望远的个人页面 - 开源中国社区1

    Java异常处理设计是Java编程中一个至关重要的环节,它直接影响到程序的稳定性和可维护性。在Java中,异常处理是通过try-catch-finally语句块来实现的,主要涉及两大类异常:编译时异常(Checked Exception)和运行时...

    常见异常处理方案

    在Java编程中,异常处理是程序健壮性的重要组成部分。异常是程序运行时遇到的错误,如果不妥善处理,可能会导致程序崩溃。以下是一些常见的Java异常及其处理方案: 1. **`java.lang.NullPointerException`**: 当...

    VC++异常处理实现原理

    ### VC++异常处理实现原理详解 #### 概述 在深入了解VC++异常处理的具体实现之前,我们需要明确几个基本概念:**结构化异常处理**(Structured Exception Handling, SEH)是一种用于处理程序运行期间发生的异常事件...

    品质异常处理单(表格模板、DOC格式).doc

    《品质异常处理单》是企业质量管理中不可或缺的一部分,主要用于记录和处理生产过程中出现的质量问题,以确保产品质量符合标准,防止不良品流入市场,保护企业声誉并维护客户满意度。以下将详细解析这一表格模板的...

    ORACLE异常处理剖析.pdf

    Oracle异常处理是数据库管理和应用程序开发中的关键环节,它涉及到对程序执行过程中可能出现的错误和异常情况进行有效管理和响应。Oracle数据库,作为一款广泛使用的商业关系型数据库管理系统,提供了强大的异常处理...

    NET异常处理规范.docx

    .NET异常处理规范是确保应用程序稳定性和健壮性的重要实践。在.NET开发中,遵循一定的异常处理规则能够有效地预防程序意外终止,提供更好的用户体验,并有助于调试和维护。以下是一些关键的异常处理原则和最佳实践:...

    Java 异常处理的 9 个最佳实践

    Java异常处理的9个最佳实践涵盖了开发者在进行Java编程时应当遵循的一系列规则和方法,以确保代码的健壮性和可维护性。异常处理是编程中的一个重要部分,它能够帮助我们更有效地管理和响应程序运行时的错误情况。 ...

    java开发异常处理与日志规范

    对于非稳定代码,应具体捕获不同类型的异常并采取相应的处理措施,而不是一概而论。 4. **处理捕获的异常**:捕获异常后,要么处理它,要么将异常向上抛出给调用者。最外层的业务代码必须处理异常,并将其转化为...

    java异常处理ppt

    在Java编程中,异常处理是一项至关重要的机制,它允许程序员优雅地处理程序运行时可能出现的问题,而不是让程序突然崩溃。Java异常处理主要涉及以下几个核心概念: 1. **异常(Exception)**:异常是程序在执行过程...

    第6章除法运算——异常处理.ppt

    总的来说,通过学习和掌握异常处理机制,开发者可以编写更加健壮的代码,确保程序在遇到问题时不会无谓地崩溃,而是能够提供有用的错误信息或采取适当的恢复措施。这对于提升软件的稳定性和用户体验至关重要。在进行...

Global site tag (gtag.js) - Google Analytics