What should be considered when writing new exception classes?
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.
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.
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.
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!
Basically there are three categories of 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
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.
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.
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.
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.
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:
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