OdeToCode IC Logo

Error Handling

Friday, February 4, 2005

When looking at the code for a product or library, I find I’m always drawn to look at the error handling and validation pieces. Since every piece of software has these pieces in one form or another it’s always interesting to compare and contrast the different practices and methodologies used throughout the industry. The newly released Enterprise Library, being from the patterns and practices group, obviously had some thought put into this area, so I was keenly interested to peek at the code.

Here is one of the constructors from the Enterprise Library’s ConfigurationBuilder class:

   66 public ConfigurationBuilder(string configurationFile)

   67 {

   68    ArgumentValidation.CheckForNullReference(configurationFile, "configurationFile");

   69    ArgumentValidation.CheckForEmptyString(configurationFile, "configurationFile");


   71    LoadMetaConfiguration(configurationFile);

   72 }

The code snippet is short, but tells a tale. It tells me I can expect the Enterprise Library to validate explicitly all the parameters I pass.

The code snippet also tells me the team made a decision to let constructors throw exceptions. Deciding to let exceptions escape from a constructor is not an easy decision, particularly in this case because the ConfigurationBuilder class inherits from IDisposable. If the constructor acquires a resource (say, opens a configuration file) and then throws - there is no object reference returned by the constructor for the client to invoke Dispose upon.

On the other hand, covering this edge condition always increases the complexity of the internal implementation, and can also make the public interface harder to use (for instance if the client has to invoke both a constructor and an Initialize method).

It's a tough tradeoff - 'simple elegance' or 'paranoid error handling'. Which do you prefer?

John Friday, February 4, 2005
It's OK to throw from your constructor provided you do it *before* aquiring a resource. Even aquiring a resource isn't really a killer problem, because the finalizer will catch it.
<br>The real problem is when you're IDisposable *and* you subscribe to events from the constructor, then throw. Think about it. It's leak-o-riffic!
<br>I think validating your arguments and asserting any other state (i.e. globals) by throwing from a public constructor is fine, but you should always do it first (you should do it first for any method for that matter.)
Raymond Lewallen Friday, February 4, 2005
I agree with John. My practice is to do the same thing, always check the ctor parameters (or like John said, any method) prior to acquiring resources, even in type that implement IDisposable, and this is a safe way to handle it. I prefer a combination of both, making my preference &quot;simply elegant paranoid error handling&quot;, which is how I view what the EntLib does. You can get more elegant and you can get more paranoid, but I think the EntLib developers found a happy medium.
Darrell Friday, February 4, 2005
It depends. :)
<br>Simple elegance if only I'm going to be using it (an internal method where I make sure I'm only passing in good stuff), paranoid error handling if it is ever going to be accessed by someone else (there is some chain of method calls that can allow unchecked data into that method).
Thomas Eyde Saturday, February 5, 2005
I prefer unit tests and no paranoia.
Scott Saturday, February 5, 2005
<br>The topic was &quot;Error Handling&quot;. Do you mean I don't need to validate arguments or handle exceptions if I write unit tests?
Carl de Billy Wednesday, April 6, 2005
On my side, I prefer to use a factory pattern who can throw an exception (or return null in case of non-creation) instead of throwing it from the constructor.
<br>So, I have a strong preference for paranoid error handling. It will accelerate debugging, make the system more robust/reliable and will prevent weird behaviour caused by quick untested change in the code.
Comments are closed.