Is Your Problem Exceptional?

Error handling is frequently ignored or postponed until “after the basic functionality is working”. However, designing a standard error handling strategy is critical to producing reliable software, especially if you are writing a software library that will be used by other developers. Even if you aren’t building a library for distribution, other developers on your team or project depend on your code.

 

When should you throw an exception? As mentioned in David Abraham's discussion of exception strategies, the usual answer is that exceptions are only for unexpected cases. Unfortunately, this answer breaks down. Experienced developers are good at thinking of strange cases, but that doesn’t mean that every considered case is no longer unexpected. A better guideline is that exceptions should be returned if the caller should have known better. The calling code is using passed parameters to indicate an understanding of the situation; if that understanding is incorrect, the caller needs to know! Another useful guideline is that constructors must throw exceptions if the alternative is to return an object that is in an invalid state.

 

The best way to improve your design skills is to consider complex problems. The following scenarios define a number of situations that could be resolved through exceptions. Some are clear candidates for exceptions, in others exceptions are not the best solution. Please send me other interesting exception handling scenarios, especially ones where the right answer is debatable. I’m planning on expanding this to a story, probably with a discussion of what approach is correct for each scenario.

 

1.       You are building an online store.  The user follows an “add to cart” link that has the product ID embedded in the query string. The product ID is invalid; no such product exists in the database.

2.       You have a method Foo().  Occasionally it detects an error and needs to return error information to the caller.  Which of the following two approaches do you prefer?

2.1.             bool Foo(object param, errorInfo)                   // returns false to indicate an error, error info is set into the errorInfo param

2.2.             void Foo(object param)                                 // throws an exception to indicate problems,  error info is in the exception

3.       Revisit the above scenario: what if Foo() is a performance critical method that will be called millions of times?

4.       You write a database helper utility class that offers a static public string GetConnectionString() method.  What happens if the utility class can’t find the connection string?

5.       You are writing a StringCollection class that offers typed access to a collection of strings.  You design a public int Find(string s) method that returns the index of string s in the collection.  What if string s doesn’t exist in the collection? 

6.       You are building a framework to validate custom business rules (e.g., required fields or min/max validations).  Users of your library will define rules and then pass in data structures to be validated against those rules.  How do you indicate rule violations?

7.       You have created a new BigInt datatype that holds unlimited sized integers.  It offers a static public BigInt BigInt.Parse(string) method to create a new BigInt from a string.  How do you indicate that the string is invalid?

8.       You are writing a MP3 player to compete with Winamp.  You write code to serialize the playlist to playlist.xml when the application is closed.  When the application starts it reads in the serialized playlist, so you write an instance method like public void Playlist.ReadPlaylist(string filename).  How should that method handle the case where playlist.xml does not exist?

9.      You are designing a persistent object framework.  Every persistent object derives from a base class that provides concurrency checking and transaction support.  The derived classes override an protected abstract Save() method that will be called by the base class.  You need to decide how the derived classes should indicate problems to the base class.

 

Feedback appreciated.

 

 

No Comments