The Tao of development

learning and disseminating new ways of developing software

Exception management

Exceptions are special cases that deviate from the normal behavior in a software routine and need to be cared for exceptionally, at least to inform that they occurred. Their cause might include: process deviation, malformed data, infrastructure or connectivity issues, poor quality business rules, etc. Exception management is the practice of resolving and handling such occurrences by using software tools. Good exception management can contribute to efficiency of business processes.

The definition above states what an exception is in formal terms. In our daily experience an exception is only a fail in the normal flux of our software. These fails are intrinsic in software development and they will exist no matter how extensive and carefully you run your tests. So faced with this what can we do? How we can handle these fails?

At this point we have to split point of view into two streams:

  • Framework or library developer
    • Create code that other developer will invoke / use;
    • Must create flexible and easy to implement interfaces ;
    • The library can’t be  a stopper for mocking or testing tasks.
  • High level software developer
    • Consumes a framework or libraries and create very business oriented code;
    • In general holds a user interface that is operated by a human.
    • 

The framework developer approach

When we develop something that will be used by another developer we need extra care. We must be sure that our  code will run on any environment with only a minimum change in its configuration. This code can’t be hard do interact because we don’t know how skilled the developer is or the time frame he have. With this in mind I collected some rules of thumb for this scenario:

  • Every library must have its own exception class

It’s a class located in the root of the library. If any exception occurs in your code and you want to propagate it to the next level send it as an inner exception of this class.
Don’t use this exception class to implement any logging logic. If you do this you will create a tight coupling between your library and the logging service and it’s not a good idea.

The exception class must implement the minimum interface required by the platform. In the .NET it means something like:

using System;
using System.Runtime.Serialization;

namespace ExampleLibrary
{
    /// <summary>
    /// This class transport all errors that occurs on ExampleLibrary.
    /// </summary>
    [Serializable]
    public class ExampleException : Exception
    {
        /// <summary>
        /// Simple constructor for injecting or other simple prupouse.
        /// </summary>
        public ExampleException()
        {
        }

        /// <summary>
        /// Create an exception that holds a message. This is usually used when you found a business exception.
        /// </summary>
        /// <param name="message">A very explicit message that explains what happened.</param>
        public ExampleException(string message): base(message)
        {
        }

        /// <summary>
        /// Create an exception object that holds both: a message and any other exception that has being caught.
        /// </summary>
        /// <param name="message">A very explicit message that explains what happened.</param>
        /// <param name="inner">The exception caught. This will keep the information about call stack that is very useful.</param>
        public ExampleException(string message, Exception inner)
            : base(message, inner)
        {
        }

        /// <summary>
        /// This will be used internally by .NET when exception must cross the borders of a process (ex: when creating web services).
        /// </summary>
        /// Data needed to serialize and deserialize an object.
        /// Describes the source and desination of serialized object.
        protected ExampleException(SerializationInfo info,StreamingContext context)
            : base(info, context)
        {
        }
    }
}

To create such classes in VS (2005, 2008 and 2010 with code snippets active) just create a new empty class and type: exception <TAB> <TAB> and voila!

  • The library must throw only it’s own exception

No matter what happened: if you need th throw an exception you will throw the library exception.
Why?
This is more related with the catch operation. In .NET it’s not a good practice to use a catch like this:

try
            {
                var a = 0;
                var b = 10;
                var c = b/a;
            }
            catch (Exception e)
            {

                // do something with the exception
            }

When .Net found a catch like this it will try to find the real type of the exception and will search through a list with all available exception types in the current application domain. This is a very time consuming operation.
To avoid this you need to catch more specific exceptions, like in the following code snippet:

try
            {
                var a = 0;
                var b = 10;
                var c =  Math.Sqrt(b / a);
            }
            catch (DivideByZeroException dbze)
            {
                // do something with the exception
            }
            catch (ArithmeticException ae)
            {
                // do something with the exception
            }

In this simple snippet we have only two types of exception to catch (in the truth you can choose catch only the second) but imagine if you are sat on top  of a call to a large operation (where we have database transactions, calculations and web services interactions): how many stacked catches will you need? And how you will discover them all?  

That’s why we throw only one kind of exception by library. It’s more easy and cleaner to catch the exceptions.

Wrapping the exceptions is very simple like the code below can demonstrate:

try
{
    var a = 0;
    var b = 10;
    var c =  Math.Sqrt(b / a);
}
catch (DivideByZeroException dbze)
{
    throw new ExampleException("This is a very explicity message", dbze);
}
catch (ArithmeticException ae)
{
    throw new ExampleException("This is, also, a very explicity message", ae);
}

This is very easy indeed, but requires code… soon I will post about AOP (Aspect Oriented Programming). AOP will help us to do this, and many other things, without code or without intrusive code.

  • Throw exceptions only when they are relevant or you can’t handle them

Exceptions are exceptional and should be treated as such. If something exceptional, unusual, or generally “not supposed to ordinarily happen” then an exception is a reasonable thing to do. You shouldn’t throw exceptions for things that happen all the time. Then they’d be “ordinaries”.

A good trick to know when you should throw an exception is: Method’s names indicates what actions (verbs) they should do. Throw an exception when they can’t do what it says it can.

Inside your library you should try to handle as much exception as you can.  But sometimes it’s no possible to work arround or there is no fall back to an operation that fails if you reach this point wrap the original exception inside your library exception and throw it.

The high level developer approach

On the other side of the development cycle we found developers that consume the artifacts built by framework developers. The guys who play this role have different needs:

  •  Avoid raw exceptions to reach user interface

 It’s very bad when a user sees the Yellow Page Of Death on your website ! Or when our customer says that the windows application you deployed is trying to send data to Microsoft’s support. No matter which exception has been thrown or whom threw the exception it can’t reach user interface without being treated. High level developers should handle exceptions in a normal way (try … catch) but they also needs to implement some mechanism to catch all others exceptions left behind because “it  will never happen” until they happen.

In web applications based on .Net platform you can manipulate those wild exception in hooking the Error event. This very easy to implement this way but it means more code to implement (and sometimes more code also means more bugs :( ) and to maintain. A good alternative to this approach is to use an external system that watches for our application errors. A very good example of this kind of software is Elmah. It also helps to solve a problem that I will post about: Application Logging. You don’t need to write a line of code to put elmah running on your site you just need to deploy its dlls on the bin folder an adjust the web.config.

On the other side, windows applications have several ways to create this global exception handling but all of them implies in creating more code.  You also can change the way .Net handle these exceptions by changing its behavior through the configuration method SetUnhandledExceptionMode.

When the exception is critical and there is no way to avoid the stop of program’s normal flow you must kindly and gracefully inform the user about it. If possible you can ask if user wants to try again the faulty operation (maybe changing some parameter to see if it works). The code below show an example of how to configure and handle unhandled exceptions:

// Starts the application.
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlAppDomain)]
public static void Main(string[] args)
{
    // Add the event handler for handling UI thread exceptions to the event.
  Application.ThreadException += new ThreadExceptionEventHandler(ErrorHandlerForm.Form1_UIThreadException);

  // Set the unhandled exception mode to force all Windows Forms errors to go through
    // our handler.
    Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

    // Add the event handler for handling non-UI thread exceptions to the event.
    AppDomain.CurrentDomain.UnhandledException +=
  new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

    // Runs the application.
  Application.Run(new ErrorHandlerForm());
}

// Programs the button to throw an exception when clicked.
private void button1_Click(object sender, System.EventArgs e)
{
  throw new ArgumentException("The parameter was invalid");
}

// Start a new thread, separate from Windows Forms, that will throw an exception.
private void button2_Click(object sender, System.EventArgs e)
{
  ThreadStart newThreadStart = new ThreadStart(newThread_Execute);
  newThread = new Thread(newThreadStart);
    newThread.Start();
}

// The thread we start-up to demonstrate non-UI exception handling.
void newThread_Execute()
{
    throw new Exception("The method or operation is not implemented.");
}

// Handle the UI exceptions by showing a dialog box, and asking the user whether
// or not they wish to abort execution.
private static void Form1_UIThreadException(object sender, ThreadExceptionEventArgs t)
{
  DialogResult result = DialogResult.Cancel;
    try
    {
  result = ShowThreadExceptionDialog("Windows Forms Error", t.Exception);
    }
    catch
    {
        try
        {
            MessageBox.Show("Fatal Windows Forms Error",
                "Fatal Windows Forms Error", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Stop);
        }
        finally
        {
            Application.Exit();
        }
    }

    // Exits the program when the user clicks Abort.
    if (result == DialogResult.Abort)
        Application.Exit();
}

// Handle the UI exceptions by showing a dialog box, and asking the user whether
// or not they wish to abort execution.
// NOTE: This exception cannot be kept from terminating the application - it can only
// log the event, and inform the user about it.
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
    try
    {
        Exception ex = (Exception)e.ExceptionObject;
  string errorMsg = "An application error occurred. Please contact the adminstrator " +
            "with the following information:\n\n";

        // Since we can't prevent the app from terminating, log this to the event log.
  if (!EventLog.SourceExists("ThreadException"))
        {
            EventLog.CreateEventSource("ThreadException", "Application");
        }

  // Create an EventLog instance and assign its source.
  EventLog myLog = new EventLog();
        myLog.Source = "ThreadException";
  myLog.WriteEntry(errorMsg + ex.Message + "\n\nStack Trace:\n" + ex.StackTrace);
    }
    catch (Exception exc)
    {
        try
        {
            MessageBox.Show("Fatal Non-UI Error",
                "Fatal Non-UI Error. Could not write the error to the event log. Reason: "
                + exc.Message, MessageBoxButtons.OK, MessageBoxIcon.Stop);
        }
        finally
        {
            Application.Exit();
        }
    }
}

// Creates the error message and displays it.
private static DialogResult ShowThreadExceptionDialog(string title, Exception e)
{
  string errorMsg = "An application error occurred. Please contact the adminstrator " +
        "with the following information:\n\n";
  errorMsg = errorMsg + e.Message + "\n\nStack Trace:\n" + e.StackTrace;
  return MessageBox.Show(errorMsg, title, MessageBoxButtons.AbortRetryIgnore,
        MessageBoxIcon.Stop);
}
  • Leave a track of what happened

As a high level developer, probably, you’ll be the first one to be interrogated about some problem with the application. That’s why you should write the exception to somewhere. No matter if it’s a file on the disk a table on a database or a call to a web service. The reason why you should preserve the exception data is that you will need to correct the problem! Some times the exception’s trigger is hard to reproduce in test or development environment. In my experience have a good exception tracking can drastically reduce the time to understand and find the exception.  When you write to repository you should remember that besides the exception data you also need to preserve environment data because sometimes the exception’s trigger only exists in a specific environment.   AOP will help us with this task and I’ll show how on a post.

Summary

  1. One exception class per library (dll);
  2. Libraries throws only one type of exceptions (different exceptions can be wrapped by the library exception);
  3. If you can handle the exception do it. If you can’t, let it bubble up;
  4. Don’t use exceptions to control execution flow;
  5. Never let the application break down on user’s hand. Always implement a global handler for unhandled exceptions;
  6. Save the information about the occurrence of the exception. You will need it to track down the problem.

Hope you enjoyed the information and that help you in your daily tasks.

Happy coding!

Follow

Get every new post delivered to your Inbox.