在这种情况下,在异常中执行代码是不是很糟糕?

时间:2016-12-11 18:14:07

标签: java

我有这个具体情况:

  1. 我的例外有代码和本地化消息
  2. 投掷者只知道代码
  3. 捕手需要本地化的消息
  4. 本地化位于数据库表中
  5. 这样的事情是错的:

     public class MyException{
        public MyException(int code){
           try{
              this.message = db.selectMessage(code);
           }catch(Exception ex){
              this.message = "";
           }
        }
     }
    

    这将完全隐藏投掷者消息本地化的事实。

    或者我应该这样做:

       public class ExceptionUtils{
           public static throwMyException(int code) throws MyException{
               String message = db.selectMessage(code);
               throw new MyException(code, message);
           }
    
    }
    

    但这需要投掷者知道这个工具。

5 个答案:

答案 0 :(得分:1)

我建议使用ResourceBundle类,因为它是广泛接受的本地化方式。这样您就可以将消息存储在与DB相对的文件中。另外,从这些文件中读取消息由JVM处理,您无需为其编写自己的代码。但是,如果您坚持使用数据库,我会在应用程序初始化期间将所有消息从数据库读入文件系统或内存,然后您不必从数据库读取数据库,并且每个异常都会导致数据库连接失败。

答案 1 :(得分:1)

这是一种更好的方法:

public class MyException extends Exception {
    private int code;

    public MyException(String message, int code) {
        super(message);
        this.code = code;
    }

    public int getCode() {
        return code;
    }
}

用法:

Integer messageCode = null;
try {
    // do stuff
} catch (MyException e) {
    logger.log(e.getMessage(), e); // log actual message
    messageCode = e.getCode();
}
if(messageCode != null /* && you really want to show it to end user */) {
    String localizedMessage = db.selectMessage(code);
    // show localized message to end user
}

Adavantages:

  • 您不需要Util类来抛出异常。
  • 每次抛出异常时都不需要访问db,但是 只有当你抓住它并且"决定"如果你想要获取消息 向用户展示。
  • 您不需要在另一个例外中捕获异常。
  • 您不会丢失实际的非本地化消息。
  • 如果db.getMessage()失败并且抛出异常,您将不会丢失实际的堆栈跟踪。

编辑:

关于if部分是否是个好主意存在争议,所以我必须详细说明。

messagelocalized version of message,这些非常不同。

消息:

  • 是对出错的描述。
  • 是在发生异常时在控制台和日志记录中看到的内容。
  • 是英文。
  • 必须在任何条件下显示,如果没有显示,则认为这是一种非常糟糕的做法。

本地化消息:

  • 是Message的翻译,为了最终用户而非程序员。
  • 不是英文。
  • 预计
  • 不会在控制台或日志记录中显示。
  • 只有在UI中与最终用户交互时才需要
  • 不应用于非UI相关的代码部分。

在提问者提供的实际代码中,messagelocalized message替换,这违反了精心设计的异常的预期行为,因此我将这两者分开。在我的代码中,message显示为始终,并且可以在发生异常时记录,无论是否有任何条件;只有localized message才能获取您实际需要与最终用户进行交互的IF。因此,当您不与它们交互时,可以跳过对DB的访问。

答案 2 :(得分:0)

catch块设计用于在程序中发生异常后执行某些操作,因此我建议您在catch块中提供一些异常处理代码,因为它将允许其他人有效地理解您的程序

答案 3 :(得分:0)

只要代码可以帮助您最好地处理异常

,它就不错了

答案 4 :(得分:0)

问题是运动部件太多了。如果catch块中的数据库访问因抛出异常而失败 - 并且由于多种原因导致其失败 - 那么您甚至不会看到原始异常。您在catch块中执行的任何操作都可以执行异常操作。

事实上,最近发生在遗留代码中的事情(不同的语言,虽然相同的想法)。当你知道你的生产系统因某些特定原因而失败但你不知道具体原因是什么时,人就是痛苦......

可能是您的例程db.selectMessage()本身受到保护并且不会抛出异常。那好吧。但是你有责任在你写的每个捕获区中检查它。最好采用一种设计方法,除了已知的“安全”之外,不会涉及任何可以做任何事情的捕获块。

在某些语言中,顺便说一句,捕获所有异常会捕获一些非常讨厌的异常(在Java中,那些通常不是java.lang.Exception的子类)。有时候你真的不想做任何不必要的事情,因为你不知道自己处于什么状态以及会发生什么。

在这种情况下,您可能会在某处(或以其他方式通知用户)记录该异常。该日志代码是(或应该)集中在您的应用程序中。这是一个仔细翻译/本地化/解释异常代码的地方......在某个地方你可以确保它的工作和受到保护......就像记录代码本身一样。