Sunday, September 21, 2014

Simple Exception Handling

I think any developer with any amount of experience would agree that one thing you do not skip, rule-bend, or even do poorly is exception handling. I would add that it can be tough to justify complicating error handling by turning it into its own subsystem with a bevy of objects and possibilities.

For what it’s worth here are a bare-minimum-yet-good-enough-for-most-common-business-application-development exception handling rules:  Do it, Be consistent, Keep it simple, Throw in the kitchen sink, Roll your own, Always at initial point of action

Do it
This is nonnegotiable, you use exception handling.

Be consistent
Be consistent across the solution. Everyone working on the project knows the simple rules and follows them in the same way.

Keep it simple
The simpler it is the more likely everyone will do it and be consistent. Make people justify any specialized exceptions.

Throw in the kitchen sink
Throw exceptions with every bit of data that could possibly be available to help the coder determine what happened.

Roll your own
Don’t call Parse on a type and let the code throw a “wrong format” exception, rather call TryParse and then throw in the kitchen sink when it does not work.

Always at initial point of action
Catch and handle exceptions at the initial point in the application where the system is sprung into action. In the common business application, this is often behind a button click or some other event handler for a user control. In other words, when a process (no matter how small) kicks off, wrap the call in a try-catch block and handle any exception gracefully. I often tell people that the only code in an event handler for a user control should be a try-catch block with a call to the action’s handler.


private void btnAddFileToRelease_Click(object sender, EventArgs e)
{
       try
       {
              TryAddingFileToRelease();
       }
       catch (Exception ex)
       {
              HandleException(ex);
       }
}

Notes
Unlike the old days, most modern programming environments provide a full call stack in an exception, so we know exactly where the routine bombed. Because of this we often don’t need exception handling all over the place. We need it at the initial point of action so our application stops gracefully and we need it when objects must be disposed.

Creating custom exceptions: Some coders seem to do this for every new exception they think of, often inheriting some base exception. This is poor OO programming to begin with even though it might look cool. A generic exception with a message that explains the unique error will suffice in 99% of the cases. Like many things I vote to keep exception handling simple before it turns into a subsystem all to itself that the next guy has to comprehend and maintain. Create a special type of exception if the code will behave differently because of the type. For example, if an exception is a network down exception, then the code might try again n-number of times.

Simple Exceptions: Often code “knows” the context of a call and thus might know that a user could fix the issue. In this case a special Simple Exception could be thrown. When the exception reaches the client interface the exception could be handled differently. Instead of logging the error and emailing support, a message could be displayed to the user allowing them to fix the issue before trying again.

For example, a system may allow users to define Widget Types and import Widgets into the system. During an import a Widget Type Key is read and the system looks up the Widget Type using they key. The code that does this could throw a Simple Exception if the Widget Type is not found.  The user would then get the message, set up the new type, and try the import again.
Just make sure your assumptions about whether or not the issue is user-addressable are valid. Often these assumptions that lead to Simple Exceptions being thrown are high on the call stack and not deep in the bowels of the system.

We can have just two kinds of errors, one for developers (Those that a developer needs to look at (and wants the kitchen sink)) and one for users (those that an end user can take corrective action for (given a much simpler explanatory message))

We should create specialized exception classes when the code behaves differently. So it would seem at a minimum we might have 3 types; regular, simple, and common.

Regular ones might get logged and emailed to the development team.
Simple ones might just get displayed to the user.
Common ones get caught and dealt with by code, like trying an operation again in case of slow network response, locked files etc.

It’s fine to start with just two types of exceptions and another one added for common issues that the code might be able to handle.

It may be a different case where a developer wants to explicitly state that a method may return one or more reasons why a process cannot be completed.

No comments:

Post a Comment