Effective Use Of Exceptions

Improve Your Code By Using Exceptions Effectively

© James Huw Evans

Oct 11, 2007
Treating exceptions like any other major system component can lead to better software.

Programming languages such as Java and C# define a concept called exceptions. A run-time exception indicates the occurrence of an event (*) a piece of code. One part of a program will throw an exception and another part of that program will catch it.

Using Exceptions

Many of the classes in C#/.NET's framework throw exceptions. The StreamReader class throws a number of exceptions as part of its constructor. The code below tries to create a StreamReader object (reader) to read from the file called nosuchfile.txt. This file does not exist so when this code is run, the StreamReader constructor throws a FileNotFoundException. This exception is caught by providing a catch block that specifies the FileNotFoundException class and its object reference name (nofile).

using System.IO;

public void m()

{

try

{

StreamReader reader = new StreamReader("nosuchfile.txt");

}

catch(FileNotFoundException nofile)

{

Console.WriteLine(nofile);

}

finally

{

// Code here always executed }

}

This code indicates the basic contract of programming with exceptions. Code that can possibly throw an exception is placed into a try block and the exceptions that the try block may throw are handled in separate catch blocks. If the code within the try block can throw more than one type of exception (StreamReader throws five types of exception) a catch block for each can be specified, or a class that is common to a number of raised exceptions can be used. For example, StreamReader throws DirectoryNotFoundException, FileNotFoundException and IOException. The first two are subtypes of IOException. Therefore, a single catch block for IOException can be used and if either a DirectoryNotFoundException or a FileNotFoundException are thrown, the code in the IOException catch block will be executed.

It makes sense to specify a supertype in this way if two or more exceptions can be treated in the same way at run-time. When using a single catch block it is not possible to tell which class of exception is being dealt with, unless the type of the exception object is tested at run-time (which should probably not be done). Using two catch blocks can mean the code's complexity is reduced.

Don't be tempted into catching (and throwing) just Exception. This means all subtypes of Exception will be caught by the same piece of code. This leads to a one-size-fits-all catch block that tries to handle every conceivable type. It's much better for code quality and long-term maintainability for to catch and handle exceptions individually.

The finally block above is always executed, regardless of whether or not an exception is thrown. The finally block can be used to tidy up after code in the try has failed. For example, when attempting to open two files to copy from one to another, the file for read may open OK, but the write file may fail to open. In the finally block the open read file can be closed.

When implementing a system it is a good idea to give as much time to the design of the exception model as with any other major system component. Exceptions are an important part of a program’s control flow and its error handling and reporting system. Getting it right from the start will make the code more maintainable and flexible in the future.

Defining Your Own Exceptions

When designing a method signature, what exceptions it throws should be considered. If a method has one or more exceptional cases, it’s a good idea to capture each case with a unique exception class.

In Java and C#, exceptions are classes like any other. An exception class hierarchy should be defined that reflects the exceptional events in the business or subject domain. It can be useful to think of exceptions as a way of communicating information to code elsewhere in the program. Informative names should be given to an exception's class and the class should define useful operations and contain appropriate state.

Throwing The Exception

Exceptions should be used for exceptional events. Don't use them as another way of returning data from a method call. The return statement should be used for that.

Try to limit the number of exceptions that any one method throws. This makes it easier to call the method as fewer exceptions have to be caught and it makes it easier to write and maintain the method. If a method throws more than about five exceptions, it may be time to look into refactoring it, possibly splitting it into a number of methods.

Catching The Exception

When catching an exception, the exception can either be caught and logged, or the exception can be caught and remedial action taken to correct the issue so that the exception does not occur the next time the method is called.

To take remedial action to ensure that the exception won't be thrown again, the exception should be caught as close as possible to its point of generation. This keeps the code that will attempt to correct the issue near the method call (or code block) that generated the exception. Keeping them close ensures that any objects that need to be used by the method don't have to be passed around a large part of the program.

C# does not require a program to provide an explicit catch block for code that may throw an exception. In this case, the exception is automatically thrown up the call stack to the nearest appropriate catch. This can be useful if an exception will be caught by code higher up the callstack, removing the need to explicitly catch the exception just to rethrow it. However, this can lead to code that throws exceptions too far from their generation point which can lead to catch blocks that have to catch very general exception types. For these reasons it is preferable to catch the exception as close to its points of generation as possible.

Conclusions

Exceptions are a useful language mechanism for indicating that an unusual event has occurred. By carefully designing an exception class hierarchy and by using them appropriately a useful and effective exception model can be designed and more easily maintained.

(*) Not to be confused with C# events which is a separate and unrelated concept.


The copyright of the article Effective Use Of Exceptions in Computer Programming is owned by James Huw Evans. Permission to republish Effective Use Of Exceptions in print or online must be granted by the author in writing.




Post this Article to facebook Add this Article to del.icio.us! Digg this Article furl this Article Add this Article to Reddit Add this Article to Technorati Add this Article to Newsvine Add this Article to Windows Live Add this Article to Yahoo Add this Article to StumbleUpon Add this Article to BlinkLists Add this Article to Spurl Add this Article to Google Add this Article to Ask Add this Article to Squidoo