`
ssxxjjii
  • 浏览: 948825 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

改善异常处理的 6 个技巧

 
阅读更多

在软件开发过程中,往往会出现一些不可预知的错误,这些错误有可能花费你数小时甚至数天的时间。异常处理通常是防止这种未知错误的常用措施,它的好处是你不用再绞尽脑汁去考虑各种错误,这为处理某一类错误提供了一个很有效的方法,使编程效率大大提高。

本文将为你介绍6个技巧,来帮助你提高异常处理的能力。

1.  使用一个单一的、系统范围的异常类

不要针对每种异常类型创建单独的类,而是只创建一个,并使它继承RuntimeException。这可以减少类的数量,并移除你不会去处理的需要声明的异常。

我知道你在想什么:如何告诉异常处理程序,这些是否是同一类型?如何跟踪特定类型的属性?继续读下去。

2.  为错误代码使用枚举

大多数开发者会把导致异常的原因放到消息中,出现异常时,查看日志文件即可。但是这也有一些缺点:

  • 消息不能被翻译
  • 消息不能很容易地映射为易读的文本
  • 无法从程序方面对消息进行检查

由于每个开发者的语言习惯不一样,同样的错误可能有不同的描述形式。


更好的办法是使用枚举来表示异常的类型。针对每种错误创建一个枚举,并使枚举实现一个ErrorCode接口,然后将它引用为异常中的一个字段。

当抛出异常时,只需在适当的枚举中传递即可。

Java代码 复制代码
  1. throw new SystemException(PaymentCode.CREDIT_CARD_EXPIRED);  
throw new SystemException(PaymentCode.CREDIT_CARD_EXPIRED);


现在,当你需要测试具体情况时,只需比较异常代码即可。

Java代码 复制代码
  1. catch (SystemException e) {   
  2.   if (e.getErrorCode() == PaymentCode.CREDIT_CARD_EXPIRED) {   
  3.   ...   
  4.   }   
  5. }  
catch (SystemException e) {
  if (e.getErrorCode() == PaymentCode.CREDIT_CARD_EXPIRED) {
  ...
  }
}


在资源包中使用错误代码作为关键字进行检索,即可取回易读的、国际化的文本。

Java代码 复制代码
  1. public class SystemExceptionExample3 {   
  2.     
  3.     public static void main(String[] args) {   
  4.         System.out.println(getUserText(ValidationCode.VALUE_TOO_SHORT));   
  5.     }   
  6.     
  7.     public static String getUserText(ErrorCode errorCode) {   
  8.         if (errorCode == null) {   
  9.             return null;   
  10.         }   
  11.         String key = errorCode.getClass().getSimpleName() + "__" + errorCode;   
  12.         ResourceBundle bundle = ResourceBundle.getBundle("com.northconcepts.exception.example.exceptions");   
  13.         return bundle.getString(key);   
  14.     }   
  15.     
  16. }  
public class SystemExceptionExample3 {
 
    public static void main(String[] args) {
        System.out.println(getUserText(ValidationCode.VALUE_TOO_SHORT));
    }
 
    public static String getUserText(ErrorCode errorCode) {
        if (errorCode == null) {
            return null;
        }
        String key = errorCode.getClass().getSimpleName() + "__" + errorCode;
        ResourceBundle bundle = ResourceBundle.getBundle("com.northconcepts.exception.example.exceptions");
        return bundle.getString(key);
    }
 
}


3.  在枚举类型中添加错误代码

在某些情况下,一个数字形式的错误代码可以对应一个异常,例如HTTP响应。在这种情况下,在ErrorCode接口中添加一个getNumber方法,并在每个枚举类型中实现它。

Java代码 复制代码
  1. public enum PaymentCode implements ErrorCode {   
  2.   SERVICE_TIMEOUT(101),   
  3.   CREDIT_CARD_EXPIRED(102),   
  4.   AMOUNT_TOO_HIGH(103),   
  5.   INSUFFICIENT_FUNDS(104);   
  6.     
  7.   private final int number;   
  8.     
  9.   private PaymentCode(int number) {   
  10.     this.number = number;   
  11.   }   
  12.     
  13.   @Override  
  14.   public int getNumber() {   
  15.     return number;   
  16.   }   
  17.     
  18. }  
public enum PaymentCode implements ErrorCode {
  SERVICE_TIMEOUT(101),
  CREDIT_CARD_EXPIRED(102),
  AMOUNT_TOO_HIGH(103),
  INSUFFICIENT_FUNDS(104);
 
  private final int number;
 
  private PaymentCode(int number) {
    this.number = number;
  }
 
  @Override
  public int getNumber() {
    return number;
  }
 
}



这些数字可以是全局唯一的,或者每个枚举类型只对应一个数字。你甚至可以使用隐式ordinal()方法,或者从一个文件/数据库中加载一些数字。

4.  将动态字段添加到异常处理中

好的异常处理也意味着记录相关数据,而不仅仅是堆栈跟踪。这样做会节省你大量用于诊断和重现错误的时间。当你的程序停止工作时,也无需客户告诉你,他们做了什么。

做到这一点最简单的方法是在异常处理中增加一个java.util.Map字段。该字段主要作用是保留所有异常相关的数据。如果你使用fluent interface(连贯接口)模式,你还需要添加一个通用的setter方法。

抛出异常,并带有相关的数据,类似于下面的形式:

Java代码 复制代码
  1. throw new SystemException(ValidationCode.VALUE_TOO_SHORT)   
  2.   .set("field", field)   
  3.   .set("value", value)   
  4.   .set("min-length", MIN_LENGTH);  
throw new SystemException(ValidationCode.VALUE_TOO_SHORT)
  .set("field", field)
  .set("value", value)
  .set("min-length", MIN_LENGTH);


5.  防止不必要的嵌套

长且多余的堆栈跟踪,对谁都没有好处。更糟的是,它们浪费你的时间和资源。当重新抛出异常时,调用一个静态封装方法,而不是异常的构造函数。封装方法将决定何时嵌套异常,以及何时返回原来的实例。

Java代码 复制代码
  1. public static SystemException wrap(Throwable exception, ErrorCode errorCode) {   
  2.   if (exception instanceof SystemException) {   
  3.     SystemException se = (SystemException)exception;   
  4.     if (errorCode != null && errorCode != se.getErrorCode()) {   
  5.       return new SystemException(exception.getMessage(), exception, errorCode);   
  6.     }   
  7.     return se;   
  8.   } else {   
  9.     return new SystemException(exception.getMessage(), exception, errorCode);   
  10.   }   
  11. }   
  12.     
  13. public static SystemException wrap(Throwable exception) {   
  14.   return wrap(exception, null);   
  15. }  
public static SystemException wrap(Throwable exception, ErrorCode errorCode) {
  if (exception instanceof SystemException) {
    SystemException se = (SystemException)exception;
    if (errorCode != null && errorCode != se.getErrorCode()) {
      return new SystemException(exception.getMessage(), exception, errorCode);
    }
    return se;
  } else {
    return new SystemException(exception.getMessage(), exception, errorCode);
  }
}
 
public static SystemException wrap(Throwable exception) {
  return wrap(exception, null);
}


重新抛出异常的代码类似于:

Java代码 复制代码
  1. catch (IOException e) {   
  2.   throw SystemException.wrap(e).set("fileName", fileName);   
  3. }  
} catch (IOException e) {
  throw SystemException.wrap(e).set("fileName", fileName);
}


6.  使用一个有Web控制面板的中央记录器

根据你的情况,访问产品日志可能会相当麻烦。因为这可能会涉及到多个中间人。

如果你在一个多服务器环境中,事情会更糟。找到出问题的服务器,并确定该问题只影响这一台服务器,这可能相当令人头痛。
我的建议是:

  • 将日志聚合到某一位置,最好是数据库
  • 允许从Web浏览器访问该数据库

有很多方法可以做到这一点,比如:日志收集器、远程记录器、JMX代理、系统监控软件等,你甚至可以自己构建一个。一旦你拥有它,你将能够:

  • 在几秒钟内解决问题。
  • 每个异常都有一个URL对应。
  • 维护人员无需通过其他人的帮助即可确定异常原因
  • 防止测试人员为同样的错误创建多个tickets。
  • 为企业节省资金
  • 节省你的时间,不会影响你的周末度假

异常处理示例下载:NorthConcepts-Exceptions.zip
http://www.iteye.com/news/27078

分享到:
评论

相关推荐

    c++改善程序设计技术的50个有效做法

    《C++改善程序设计技术的50个有效做法》是一本由Scott Meyers撰写,侯捷翻译的书籍,...书中的其他43个做法涵盖了更多的主题,包括模板、异常处理、STL的使用、面向对象设计原则等,都是C++开发者不容忽视的重要知识。

    TCPIP高效编程-改善网络程序的44个技巧

    《TCP/IP高效编程-改善网络程序的44个技巧》这本书深入探讨了如何优化网络程序,提高其性能和效率。TCP/IP是互联网的基础协议,理解并掌握其高效编程技巧对于开发高质量的网络应用至关重要。以下是对书中部分核心...

    信号处理使用技巧后续资源包

    信号处理是信息技术中的一个核心领域,它涉及到对各种信号的采集、分析、转换和优化,以便提取有用信息或改善通信质量。"信号处理使用技巧后续资源包"很可能包含了一系列关于这个主题的教程、代码示例、工具或者研究...

    改善C#的157个建议编写高质量代码.zip

    3. **异常处理**:合理使用try-catch-finally语句,避免使用空异常处理块。对于可预见的错误,应提供具体的异常类型。 4. **代码简洁性**:避免冗余代码,利用C#的特性如lambda表达式、LINQ等简化代码。 5. **面向...

    EDA/PLD中的C++程序的异常处理技巧

    在EDA(电子设计自动化)和PLD(可编程逻辑器件)领域的C++程序开发中,异常处理是一项...记住,异常处理是C++编程中一个重要的组成部分,尤其是在关键领域如电子设计自动化,其正确实施对于系统的稳定运行至关重要。

    改善Java文档的理由建议和技巧Java开发Java经验技

    7. 包含异常处理:在文档中明确指出方法可能抛出的异常及其处理方式,帮助读者预防和解决潜在问题。 8. 用图解说明:对于复杂的流程或架构,使用图表进行解释,直观地展现系统结构和工作原理。 9. 文档风格指南:...

    TCP+IP高效编程--改善网络程序的44个技巧.zip

    30. **异常处理**:在网络编程中正确处理异常,保证程序的稳定运行。 31. **资源限制管理**:理解和应对网络编程中的各种资源限制,如打开文件描述符的数量。 32. **网络协议栈理解**:深入理解TCP/IP协议栈的层次...

    tcpip高效编程源代码(改善网络程序的44个技巧)

    本书“TCP/IP高效编程:改善网络程序的44个技巧”旨在帮助开发者优化网络应用,提高其可靠性和效率。以下是一些核心知识点: 1. **TCP/IP协议栈**:理解TCP/IP协议族的层次结构,包括链路层、网络层、传输层和应用...

    改善网络程序的技巧.rar

    在“改善网络程序的技巧.rar”这个压缩包中,包含了一本名为“网络程序的44个技巧.pdf”的文件,该文件详细阐述了提升网络编程效率和性能的多个关键知识点。以下将根据标题和描述,深入解析这44个技巧中的部分核心...

    优雅地在Java 8中处理异常的方法详解

    在Java 8中,异常处理有了新的方式,特别是在使用流(Stream) API和lambda表达式时。传统的try-catch块在lambda表达式中显得不够优雅,因为它们会破坏代码的简洁性。本文将介绍如何在Java 8中更优雅地处理异常。 ...

    07969 工厂生产及质量培训--现场工人改善的方法、技巧(DOC 5页).doc

    【工厂生产及质量培训——现场工人改善的方法、技巧】 工厂生产与质量的提升对于任何制造型企业来说都是至关重要的。这份文档旨在提供一种方法论,帮助现场工人通过改善工作流程、提高效率、保证质量和确保安全来...

    Effective C++改善程序与设计的55个具体做法(中文第三版)(高清)

    - **异常处理**:详细讲解了C++中的异常处理机制,以及如何正确地使用它来增强程序的健壮性。 - **资源管理**:介绍了智能指针等现代C++特性,用于自动管理资源生命周期,减少内存泄漏等问题的发生。 #### 5. 模板...

    改善程序设计技术的50个有效做法

    当`operator new`失败时,会抛出异常,程序员应对此做好异常处理。 除了上述几点,还有其他优化技巧,如: 8. **利用const和引用**:使用`const`修饰函数参数和成员,以及引用,可以减少不必要的复制,提高效率并...

    提升你的Java应用性能改善数据处理Java开发Java经

    "提升你的Java应用性能改善数据处理Java开发Java经验技巧"这一主题涵盖了许多关键的知识点,下面将对其进行详细的阐述。 1. **JVM调优**:Java虚拟机(JVM)是Java程序运行的基础,理解和优化JVM参数对提升性能至关...

    TCPIP高效编程:改善网络程序的44个技巧(高清带书签)

    ### TCPIP高效编程:改善网络程序的44个技巧 #### 知识点一:理解TCP/IP协议栈 - **定义与组成**:TCP/IP(Transmission Control Protocol/Internet Protocol)是一种用于互联网及类似计算机网络的通信协议。它...

    C# ATM机改善版,ATM改善版ATM改善版

    5. **异常处理** - 异常捕获:对可能出现的错误情况(如输入无效、账户不存在等)进行异常捕获和处理,提供友好的错误提示。 6. **多线程** - 同步操作:在并发环境下,如多个用户同时操作ATM,可能需要使用锁或...

Global site tag (gtag.js) - Google Analytics