批评我的异常处理策略 [英] Critique my exception handling strategy

查看:93
本文介绍了批评我的异常处理策略的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在过去的7年里,我一直在做面向对象编程,在这段时间内使用Java开关。有些事情我确信我有一个很好的把握,如最有用的设计模式。事实上,以下代码允许我在一天的时间内启动一个系统,这将处理我们现在准备实施的一个特定实例,同时灵活性足以应对未来的要求:

  public void importAndArchive(File detectedFile)throws FileNotFoundException,IOException {
文件workingCopy = returnWorkingCopy(detectedFile);
列表< String []> csvData = csvData(workingCopy);
setHeaderFields(csvData.get(0));

importData(csvData); //子类将实现这个抽象方法

archiveWorkingCopy(workingCopy);
}

我没有显示上述对我对模板方法的掌握,而是作为一个起点,讨论我的能力,这是我的OO设计能力的亮点。这种差距是一种系统的异常处理方法。实际上,你可以看到这个方法的签名我现在是在重新抛出一些异常,但实际上我已经去除了应用程序的另一个角落中的同样的事情。



在我走得更远之前,既然这是我第一次尝试特别系统的尝试,我想要一些验证我迄今为止所做的工作。我们的应用程序遍历一堆文件,处理它们,并归档它们。相当标准的票价。为了尽可能快地推出原型,我做了一个决定如下。应用程序基于(ResourceBundled)属性文件中的数据进行初始化。 ResourceBundle API中的各种方法抛出未经检查的异常,但我暂时没有真正处理它们,理由是它们将阻止应用程序启动,并且堆栈跟踪暂时可以满足要求。



然而,我选择了一个用于CSV处理的库,它引发检查的异常。 NetBeans然后让它非常容易地扩大这些异常,以开始:)以下是一个我已经重做的方法,实际上处理这些异常:

  private String detectImportHandler(File detectedFile)throws Exception {
String [] firstLine = null;

尝试{
/ *
* CSVReader抛出检查异常
* /
CSVReader csvReader =新的CSVReader(新的FileReader(detectedFile));
firstLine = csvReader.readNext();
csvReader.close();
}
catch(异常x){
throw new Exception(CSVReader无法处理文件:+ x.getMessage());
}

try {
return firstLine [1];
}
catch(异常x){
/ *
*因为我们重新抛出CSVReader的检查异常似乎最简单的
*也重新抛出null -pointer和/或array-out-of-bounds错误
* /
throw new异常(
第一行为空或没有importHandlerType字段:+ x.getMessage()) ;
}
}

上面的方法被调用,在一个循环中处理文件:

  try {
importHandlerType = detectImportHandler(detectedFile);
}
catch(异常x){
不可用FileErrors.put(detectedFile.getName(),x.getMessage());
继续;
}

不可用的FileErrors是一个Map,当我完成迭代文件时,然后,我可以使用这个地图及其包含的特定于文件的消息来处理较高级别的内容,例如日志记录,将文件移动到系统其他位置等。



无论如何,我已经够久了。我已经下载了Robust Java这本书,我希望它和SO社区,我可以改善我的能力被忽视的方面。我在SO上看到过其他类似的问题,但是我认为在实际代码的上下文中请求具体的建议可能是有益的。

解决方案

几句话:


  1. 在打包异常e时,您只需使用e.getMessage()。相反,我建议您使用新的异常(消息,e)。这将设置异常的原因,因此整个堆栈跟踪还将包含原始异常的堆栈跟踪。这对于调试异常的原因非常有用。


  2. 我建议您抛出更明确的异常,而不是抛出异常。 FileNotFoundException异常。使用Java API定义的异常,当它们有意义时。


  3. 我建议您明确指出要捕获的异常。


  4. (可选替换为2)一些开发人员倾向于 - 而不是为每种异常定义异常类 - 抛出一个包含错误键的常规异常,指示类型例外,例如新的DetailedException(GeneralBusinessErrors.PARSING_ERROR)。这使得更容易为您的业务错误分配与语言相关的资源文件。


  5. 将调试数据添加到异常可能很有用。例如,如果没有找到文件,它可能是您尝试打开哪个文件的信息。这在维护中非常有用,您可能无法使用调试器重现问题和/或调试。


  6. 有可能使您的系统日志记录任何抛出未被检查的未被捕获的异常。一般来说,记录抛出的异常(捕获或不被捕获)可能是有用的。



I've been doing object-oriented programming for most of the past 7 years, using Java on and off during that time. Some things I'm certain I have an excellent grasp of, such as the most useful design patterns. In fact, the following code allowed me to crank out a little system in under a day's time, that would handle the one particular instance we are ready to implement now, while being flexible enough to handle the future requirements I've been informed of:

public void importAndArchive(File detectedFile) throws FileNotFoundException, IOException {
        File workingCopy = returnWorkingCopy(detectedFile);
        List<String[]> csvData = csvData(workingCopy);
        setHeaderFields(csvData.get(0));

        importData(csvData); //subclass will implement this abstract method

        archiveWorkingCopy(workingCopy);
    }

I don't show the above to boast about my grasp of the template method, but rather as a starting point to discuss a gap I have in my abilities that is glaring in light of my OO design abilities. And that gap is, a systematic approach to exception handling. Indeed you can see in that method signature I am for the time being re-throwing some exceptions, but actually I've gone on to eradicate the very same sort of thing in another corner of the application.

Before I go much further though, since this is my first attempt to be especially systematic, I would like some validation of what I've done thus far. Our application loops over a bunch of files, "processes" them, and "archives" them. Pretty standard fare. One decision I've made in order to roll out a prototype as quickly as possible is as follows. The application gets initialized based on data in a (ResourceBundled) properties file. The various methods in the ResourceBundle API throw unchecked exceptions, but I am not really handling them whatsoever for the time being, on the grounds that they will prevent the app from starting, and the stacktrace can suffice for the time being.

I have however chosen a library for CSV handling which throws checked exceptions. NetBeans then made it very easy to proliferate those exceptions to begin with ;) The following is a method that I've since reworked that actually handles those exceptions:

private String detectImportHandler(File detectedFile) throws Exception {
    String[] firstLine = null;

    try {
        /*
         * CSVReader throws checked exceptions
         */
        CSVReader csvReader = new CSVReader(new FileReader(detectedFile));
        firstLine = csvReader.readNext();
        csvReader.close();
    }
    catch(Exception x) {
        throw new Exception("CSVReader unable to process file: " + x.getMessage());
    }

    try {
        return firstLine[1];
    }
    catch(Exception x) {
        /*
         * since we're re-throwing CSVReader's checked exceptions it seems easiest
         * to also re-throw null-pointer and/or array-out-of-bounds errors
         */
        throw new Exception(
                "First line null or did not have importHandlerType field: " + x.getMessage());
    }
}

The above method is being called thusly, inside a loop that processes the files:

    try {
        importHandlerType = detectImportHandler(detectedFile);
    }
    catch(Exception x) {
        unusableFileErrors.put(detectedFile.getName(), x.getMessage());
        continue;
    }

unusableFileErrors is a Map, and I figure when I am done iterating over the files, I can then use this map and the file-specific messages it contains to handle things at a higher level, such as logging, moving the files somewhere else on the system, etc.

Anyway I've gone on long enough. I have ordered the book "Robust Java" and I'm hoping between it, and the SO community, I can improve this neglected facet of my abilities. I've seen other similar questions on SO but I figure that also requesting specific advice in the context of actual code might be of benefit.

解决方案

A few remarks:

  1. When wrapping an exception e, you just use the e.getMessage(). Instead I suggest you use use new Exception(message, e). This will set the cause of the exception, so the entire stacktrace will also contain a stacktrace of the original exception. This can be very useful for debugging the cause of your exception.

  2. Instead of throwing Exception, I suggest you throw more explicit exceptions, e.g. FileNotFoundException. Use the exceptions defined by the Java API when they makes sense.

  3. Instead of catching Exception, I suggest you explicitly state which exceptions to catch.

  4. (Optional replacement for 2) Some developers prefer to - instead of defining an exception class for each kind of exception - throw a general exception containing an error key indicating the type of the exception, e.g. new DetailedException(GeneralBusinessErrors.PARSING_ERROR). This makes it easier to assign language dependent resource files for your business errors.

  5. It may be useful to add debug data to your exception. For example, if a file was not found, it could be information such as which file you tried to open. This is very useful in maintenance where you may be unable to reproduce the problem and/or debug using a debugger.

  6. It may be useful to have your system logging any thrown unchecked exceptions that are not caught. Generally speaking, it may be useful to log any exception that is thrown (caught or not).

这篇关于批评我的异常处理策略的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆