开发者

Exception-handling antipatterns [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.

Want to improve this question? Update the question so it focuses on one problem only by editing this post.

Closed 7开发者_JAVA百科 years ago.

Improve this question

Exception handling is a challenge for new and experienced developers alike. What are some examples of exception handling antipatterns that people have seen?


Bad cleanup logic

Throwing in clean up code from a destructor. This one is doubly bad, because a.) throwing from a destructor is generally bad and b.) because even if you could catch it, there isn't anything to do about it.

File::~File()
{
    if (!close(fd_)) {
        throw FileIOException("Could not close descriptor.", fd_);
    }
}

The UI from hell

 try {
    // ... lots of UI logic here ...
 } catch (Exception error) {
    alert("This program has performed an illegal operation and needs to quit.");
    System.exit(-1);
 }

Retrying without backoff

 bool has_connected = false;
 while (!has_connected) {
     try {
        EstablishConnection();
        has_connected = true;
     } catch (...) {
        // IGNORE
     }
  }


Here's one that isn't entirely unlike things that I've seen before.

try {
    methodThatThrowsSomeException1();
    methodThatThrowsSomeOtherException2();
    methodThatThrowsSomeOtherException3();
    methodThatThrowsSomeOtherException4();
    methodThatThrowsSomeOtherException5();
    methodThatThrowsSomeOtherException6();
    ...
    methodThatThrowsYetAnotherException20();
} catch (Throwable e) {
    log.error("There was a problem reading the user role");
    role = PRIVILEGED;
}


catch (...) in C++.

Probably the worst way to make your code look stable...

The same applies to any other language, where you catch exceptions you don't expect, and just swallow them silently in order to hide the error from the user. But the (...) is usually used to catch exceptions such as NULL pointer dereference or access denials, which means the error swallowed will probably manifest itself later in ways that might look totaly unrelated to the root of the problem.


My biggest pet peeve is setting up an exception inheritance hierarchy in which descendant relationships provide little bearing upon whether an exception should be caught or not. There's not much do be done about pre-defined exceptions, but my preference is to avoid throwing those and instead define new exceptions for cases where the caller should assume that the system state is fine except to the extent implied by the fact that the routine didn't return successfully, versus those where the system state is trashed. For example, if a method is supposed to open a file and return a new document object, but there's some problem parsing the file, it shouldn't kill the whole application. It should let the user know the file couldn't be opened, and then proceed as though the user hadn't tried to open the file. It's irrelevant why the file didn't open; the question is whether application state has been corrupted. Unfortunately, none of the standard exceptions are very good at dealing with that.


Using exceptions in shared libraries that are meant to be used from multiple languages / C++ dialects. Since there's no way the C++ compiler can guarantee you aren't accidentally throwing an exception back to the caller (unlike in Java) you're just setting yourself up for a crash.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜