2012-04-24 32 views
2

我正在寻找清理当前正在处理的代码库的异常混乱。如何清理异常处理?

基本设置是这样的。

我有一个是通过大量的类,看起来像这样实现的接口:

public interface TerminalMessage<E> { 

    // Override for specific return data type. 
    public E send(TerminalStream stream) throws Exception; 
} 

这些类扔了很多不同的异常,如IOException异常,InterruptedException异常等

,因为它是现在,我所做的就是调用getMessage()获取捕获的异常,并将此消息转发给ui-code。

这不是很好,因为我有时会向用户显示虚假消息,并且发现不需要的异常。

我想创建一个自定义的异常类(TerminalException),它将包装所有这些类型的异常。

但是我不确定在哪里做包装,如果包装是在第一次抛出异常(例如在输出流中)或每个send()方法中完成的。前者具有不增加太多代码的优点,但对于我来说,更有意义的是,流引发IOException而不是TerminalException。

上述设计并不能真正解决显示给用户的有时是坏信息,所以一些提示如何将抛出的异常转换成对用户有用的东西将是非常好的!

谢谢!

+2

我强烈建议你阅读这篇文章http://onjava.com/pub/a/onjava/2003/11/19/exceptions.html?page=2 – aviad 2012-04-24 07:35:44

回答

2

自定义异常是一个非常好的主意,如果你有一个有用的信息就像一个错误代码。

只是包装一切与你的TerminalException,但不要忘了原因

OR

使用抛出的第一个TerminalException:

public class MyException extends Exception{ 
    String errorMessage; 

    public MyException(String message, Exception cause){ 
    super(); 

    if(cause instanceof MyException){ 
     // already wrapped 
     errorMessage= cause.getErrorMessage();   
     initCause(cause.getCause()); 
    } 
    else{ 
     // not my Exception 
     errorMessage=message; 
     initCause(cause); 
    } 
´    

    } 

} 
+0

所以抛出一个抛出一个异常封装IOException异常的TerminalException级别(在我的自定义流类中)应该没问题? – monoceres 2012-04-24 08:16:24

+1

@monoceres我会说你应该总是在“有意义”的地方发现异常。如果您的流类可以添加比IOException提供的更多信息(如文件名,文件中的行号或重要状态),请捕获它并抛出一个包括信息和IOException的新异常作为原因。如果它不能添加新的信息,让它起泡到一个能够做到的层次。当然,你可以随意多次重复,或者有意义。 – siegi 2012-04-24 19:33:35

1

另一个选择可能是使用模板方法设计模式和“控制”其中的例外如下:

public abstract TerminalMessage<E> { 
    public abstract E doSend(TerminalStream stream); 
    public E send(TerminalStream stream) throws Exception { 
     // do common stuff here 
     try { 
      doSend(stream); 
     } 
     // catch more specific exceptions first 
     // handle all the exceptions accordingly here, thus controlling 
     // in one central location what will be thrown externally 
     catch(Exception) { 
     } 
    } 
} 

这样,所有派生类的异常处理将是相同的和本地化的,并且派生类不需要做任何特殊的事情。

0

从我尝试过的很多设计中,这是我最喜欢在一些项目中使用的最后一个。

public enum ExceptionCodes { 
     IOException("ioexception", false), 
     UserNotFound("usernotfond", true); 

     private static final String BUNDLE_NAME = "SOME_bundle_name"; 

     private final String bundleCode; 
     private final String isManagable; 

     ExceptionCodes(String bundleCode, String isManagable) { 
      this. ... 
      ... 
     } 

     public String message() { 
      // eventually get locale from somewhere, for example some threadLocal 
      return SomeBundleResolver.resolve(BUMDLE_NAME, bundleCode); 
     } 

     public Boolean isManagable() { 
      return isManagable; 
     } 
    } 

    public class MyGenericException extends RuntimeException { 
     private final ExceptionCodes exceptionCode; 
     private final Throwable throwable; 

     public MyException(ExceptionCodes exceptionCode) { 
      this.... 
      ... 
     } 

     public MyException(ExceptionCodes exceptionCode, Throwable throwable) { 
      this. ... 
      .... 
     } 

     public Boolean isManagable() { 
      return exceptionCode.isManagable(); 
     } 

     public String getMessage() { 
      return (throwable == null) ? super.getMessage() : throwable.getMessage(); 
     } 

     ... 
    } 

要点是异常代码在一个地方管理。你可以添加自定义的属性来枚举类似错误代码等。异常的许多问题之一是,如果你不知道如何处理异常,这是不可能的,你会知道如何处理上面的异常层。那么只会发生两种情况。任何异常都可以以某种格式显示给用户,或者系统必须以某种优雅的方式崩溃。属性isManagable就是这个。如果例外情况不可管理系统必须关闭。所以这个异常只是在一般错误处理程序的顶层应用程序中处理。这样你可以防止异常爆发。