我该如何清理异常处理?

时间:2012-04-24 07:29:10

标签: java design-patterns exception-handling

我正在寻找清理目前我正在处理的代码库的异常混乱。

基本设置就是这样。

我有一个接口,由许多类实现,如下所示:

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。

上述设计也没有真正解决向用户显示的有时不好的消息,因此有关如何将抛出的异常转换为对用户有用的一些提示会很棒!

谢谢!

3 个答案:

答案 0 :(得分: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); 
     } 
 ´               

   }

} 

答案 1 :(得分:1)

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

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) {
        }
    }
}

这样,所有派生类的异常处理将是相同的并且是本地化的,派生类不必执行任何特殊操作。

答案 2 :(得分: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就是这个。如果异常不可管理的系统必须下降。因此,异常仅在一般错误处理程序中的顶层应用程序处理。这样就可以防止异常爆炸。