Ctrlflow Blog

Categories


Recent Posts


5+1 Rules for Throwing Great Exceptions

CtrlflowCtrlflow

Exceptions are a good way to report problems in a structured manner. But there’s a difference between a good exception and a great exception; the former notifies the developer that there was a problem but the latter enables the developer to diagnose and fix it.

This article supplies you with five easy-to-apply rules to make the most out of your exceptions.

#1: Set a detailed message

The message should contain enough information to diagnose the problem. This may seem obvious, but this rule is ignored surprisingly often.

For example, over the past few months Ctrlflow Automated Error Reporting found 1745 unique problems in the Eclipse codebase caused by an IllegalArgumentException, but in 177 cases no message was set. In 10% of the cases not message is set at all. Moreover, a message like “Argument not valid”, which accounts for a further 13.6% of cases, also gives no indication what the argument in question was, making it hard to fix the underlying bug.

#2: Check preconditions early

It is a good habit to check your preconditions early in a method. This is especially true for null checks. While a NullPointerException is thrown automatically by the Java virtual machine, the resulting stack trace makes it often impossible to diagnose who is to blame. Consider the following method.

boolean createParentDir(File file) {
   return file.getParentFile().mkdir(); // throws NPE
}

Did this throw a NullPointerException because the caller passed null for file? Or did getParentFile() return null? An explicit precondition would have made this obvious to the developer. Given that NullPointerExceptions are the most prevalent cause of errors (they account for 23% of problems in the Eclipse codebase), it is a good idea to give yourself all the information necessary to fix them.

#3: Know your utility methods

There exist numerous utility methods, both in the Java library itself and in popular third-party libraries like Google Guava, which make checking preconditions easy.

Checking a non-null precondition early (rule #2) can thus be written concisely:

void setName(String name) {
   this.name = Objects.requireNonNull(name); 
   // Or Preconditions.checkNotNull(name);
}

Likewise, it is easy to provide a detailed message (rule #1):

void setAge(int age) {
   Preconditions.checkArgument(age >= 0, "Negative age: %d", age);
   this.age = age;
}

Note that the above constructs the message object (using String.format) only if the precondition does not hold; setting a detailed message therefore incurs very little overhead.

#4: Include the cause of the exception

If your code catches an exception and then throws an exception of its own, make sure to include the original exception as a cause. This wrapped exception can help you to better understand what went wrong in the first place.

This IllegalArgumentException is for example caused by a BadLocationException. But that exception was dropped in DefaultDocumentAdapter rather than wrapped in the IllegalArgumentException, thus wiping out any information about which IDocument implementation threw the initial exception.

Including the cause of the exception can thus help you uncover the circumstances that led to a problem.

#5: Use quotes in messages

If your message references values, quote them if whitespace matters.

If you don’t, an otherwise helpful message like Not·a·valid·URI:·http://www.ctrlflow.com/· can still confuse developers, as http://www.ctrlflow.com/ is evidently valid syntax. Unfortunately, this was not what the IllegalArgumentException complained about; it complained about the trailing space in http://www.ctrlflow.com/·.

If you follow these five simple rules, your exceptions will make diagnosing problems and fixing them much easier. There’s just one more, 5th+1 rule to remember:

#5+1: Be aware of thrown exceptions

Just because you throw great exceptions doesn’t mean that you have access to the wealth of information they contain; you need to log them and take the necessary actions in case these exceptions reveal bugs in your code.

If you are developing a server application, make sure that you regularly scan your server logs for exceptions. If you are developing an Eclipse-based desktop application or an Eclipse IDE plug-in, consider using tools like Ctrlflow Automated Error Reporting to get notified automatically whenever your users encounter an error on their machine.

Ctrlflow Automated Error Reporting

Learn more about all features