Designing Exceptions

What should be considered when writing new exception classes?

Use existing Exceptions

Prior to writing a new exception try to reuse existing ones. Code reuse is one of the primary goals of software development. But reuse must be based on semantics, not on the name. So be sure to check the documentation to the exception prior to using it.

Choose a meaningful Name

As for any class, method or variable, choose a meaningful and precise name for your exception class. It is often useful to remind the developer that an exception is a subclass of another exception by a naming convention, although this is not always possible.

Subclass Exceptions

If reusing an exception as is is not an option, consider to subclass an existing exceptions. This makes it easier for clients to catch this kind of exception. Grouping exceptions by subclassing is always a good idea.

Design Exception Class Hierarchy

It is very helpful to have an exception class as the root for all exceptions of an application. Subclasses handle different aspects of exception cases of this application. But how deep should this hierarchy be? Michael Feathers states

"Use different classes only if there are times when you want to catch on exception and allow the other one to pass through."
Clean Code , p. 109

The exception codes of smart-exceptions help to follow this rule. You simply have one exception class that distinguishes the particular exception event by the code number. But if you ever feel like checking the code in a catch clause you must write a new exception subclass.

Another reason to write a new exception class is if the context of the exception event Provide useful Information that is different from that of the other exceptions (e.g. it adds a port number information). Do not be tempted by laziness and add a property to the existing exception class that is only meaningful in some cases. Provide specific Information , write a new subclass!

Know the Exception Categories

Basically there are three categories of exceptions.

  1. JVM exceptions
    are thrown by the Java Virtual Machine. They are by definition unrecoverable and unchecked. Try to shutdown the application gracefully and restart. There is nothing more to do.
  2. System exceptions
    are thrown because of problems the system encounters with itself. There is no user interaction involved. This is most often a resource or configuration problem. These exceptions are unchecked and should be reported immediately to the system administrator to be resolved.
  3. Application exceptions
    are thrown by the application or a library because the information provided by the user was not as expected. The business process could not execute successfully because some conditions have not been met. Application exceptions are usually checked exceptions to allow the control flow to try an alternate path.

Know when to use checked or unchecked Exceptions

Create a checked exception by inheriting from Exception if it cannot be prevented by proper use of the API and it describes a situation where clients usually can recover from. Only in this case the user of a method throwing the exception will benefit from catching it. If it is not obvious if the situation is recoverable, favor unchecked exceptions.

Checked exceptions

  • force the client to handle certain error conditions.
  • document the possibility of error conditions.
  • greatly enhance the reliability.
  • overused, make an API less pleasent to use.

Create an unchecked exception by inheriting from RuntimeException for unrecoverable error situations where the client to a service cannot do anything to deal with the problem. This kind of exceptions are often used to indicate precondition violations.

By convention new Error class should not be created. Derive from runtime exception instead.

Never inherit from Throwable directly.

Provide useful Information

Exceptions should provide information to tell the client of the service what went wrong. This is especially important for checked exceptions but should be handled not different with unchecked exceptions.

Provide specific Information

If not all instances of an exception provide the same information, make two subclasses. Do not let the client of you exception guess which properties are provided.

Mind Serialization

Exceptions are serializable. Be sure that every property you add to your exception class is also serializable.

Please refer to Testing Serializability for a tip on writing tests on serializablility.

Provide a meaningful Message

The message printed to the log file should be meaningful and to the point. While Joshua Bloch states

"Lengthy prose descriptions of the failure are generally superfluous; the information can be gleaned by reading the source code.

The detail message of an exception should not be confused with a user-level error message [...]. Unlike user-level error message, it is primarily for the benefit of programmers or field service personnel [...]." Effective Java , p. 254

we deem it important that the context of the problem is obvious without knowing the source code.

Therefore we allow to provide information at a number of levels:

  1. title - a short categorizing information that can be used as dialog titles.
  2. summary - a short summary of what has happend.
  3. details - more detailed information of what has happend for an audience that is investigting the problem.
  4. implications - that what has happend has this implication on the business task that encountered the problem.
  5. todo - what can (or has to be) done to continue working?
  6. url - a reference to further static information on the problem encountered

For further information on textual presentation of failures you may have a look at chapter 4 of GUI Bloopers, especially Blooper 28: Vague error messages.

While it is true that most exceptions - with an exception of certain presentation tier exceptions - are targeted at the service personnel and software developers, we deem it nevertheless important to given as much information possible to spot and even fix the problem timely.

For smart exceptions the keys mentioned above are defined in MessageType. A code properties file may contain the following keys:

1000.title=...
1000=...
1000.details=...
1000.implications=...
1000.todo=...
1000.url=http://www.examples.com/information-system/system-messages/message-1