Foundations of Programming – pt 8 – Back to Basics: Exceptions

Exceptions are such powerful constructs that developers can get a little overwhelmed and far too defensive when dealing with them. This is unfortunate because exceptions actually represent a key opportunity for developers to make their system considerably more robust. In this chapter we’ll look at three distinct aspects of exceptions : handling, creating and throwing them. Since exceptions are unavoidable you can neither run nor hide, so you might as well leverage.


Handling Exceptions


Your strategy for handling exceptions should consist of two golden rules:
1 – Only handle exceptions that you can actually do something about, and
2 – You can’t do anything about the vast majority of exceptions


Most new developers do the exact opposite of the first rule, and fight hopelessly against the second. When your application does something deemed exceptionally outside of its normal operation the best thing to do is fail right then and there. If you don’t you won’t only lose vital information about your mystery bug, but you risk placing your application in an unknown state, which can result in far worse consequences.


Whenever you find yourself writing a try/catch statement, ask yourself if you can actually do something about a raised exception. If your database goes down, can you actually write code to recover or are you better off displaying a friendly error message to the user and getting a notification about the problem? It’s hard to accept at first, but sometimes it’s just better to crash, log the error and move on. Even for mission critical systems, if you’re making typical use of a database, what can you do if it goes down? This train of thought isn’t limited to database issues or even just environmental failures, but also your typical every-day runtime bug . If converting a configuration value to an integer throws a FormatException does it make sense continuing as if everything’s ok? Probably not.


Of course, if you can handle an exception you absolutely ought to – but do make sure to catch only the type of exception you can handle. Catching exceptions and not actually handling them is called exception swallowing (I prefer to call it wishful thinking) and it’s a bad code. A common example I see has to do with input validation. For example, let’s look at how not to handle a categoryId being passed from the QueryString of an ASP.NET page.

int categoryId;
try
{
categoryId = int.Parse(Request.QueryString["categoryId"]);
}
catch(Exception)
{
categoryId = 1;
}

The problem with the above code is that regardless of the type of exception thrown, it’ll be handled the same way. But does setting the categoryId to a default value of 1 actually handle an OutOfMemoryException? Instead, the above could should catch a specific exception:

int categoryId;
try
{
categoryId = int.Parse(Request.QueryString["categoryId"])
}
catch(FormatException)
{
categoryId = -1;
}

(an even better approach would be the use the int.TryParse function introduced in .NET 2.0 – especially considering that int.Parse can throw two other types of exceptions that we’d want to handle the same way, but that’s beside the point).


Logging


Even though most exceptions are going to go unhandled, you should still log each and every one of them. Ideally you’ll centralize your logging – an HttpModule’s OnError event is your best choice for an ASP.NET application or web service. I’ve often seen developers catch exceptions where they occur only to log and rethrow (more on rethrowing in a bit). This causes a lot of unnecessary and repetitive code – better to let exceptions bubble up through your code and log all exceptions at the outer edge of your system. Exactly which logging implementation you use is up to you and will depend on the criticalness of your system. Maybe you’ll want to be notified by email as soon as exceptions occur, or maybe you can simply log it to a file or database and either review it daily or have another process send you a daily summary. Many developers leverage rich logging frameworks such as log4net or Microsoft’s Logging Application Block.


Cleaning Up


In the previous chapter we talked about deterministic finalization with respect to the lazy nature of the garbage collector. Exceptions prove to be an added complexity as their abrupt nature can cause Dispose not to be called. A failed database call is a classic example:

SqlConnection connection = new SqlConnection(FROM_CONFIGURATION)
SqlCommand command = new SqlCommand(“SomeSQL”, connection);
connection.Open();
command.ExecuteNonQuery();
command.Dispose();
connection.Dispose();

If ExecuteNonQuery throws an exception, neither our command nor our connection will get disposed of. The solution is to use Try/Finally:

SqlConnection connection;
SqlCommand command;
try
{
connection = new SqlConnection(FROM_CONFIGURATION)
command = new SqlCommand(“SomeSQL”, connection);
connection.Open();
command.ExecuteNonQuery();
}
finally
{
if (command != null) { command.Dispose(); }
if (connection != null) { connection.Dispose(); }
}

or the syntactically nicer using statement (which gets compiled to the same try/finally above):

using (SqlConnection connection = new SqlConnection(FROM_CONFIGURATION))
using (SqlCommand command = new SqlCommand(“SomeSQL”, connection))
{
connection.Open();
command.ExecuteNonQuery();
}

The point is that even if you can’t handle an exception, and you should centralize all your logging, you do need to be mindful of where exceptions can crop up – especially when it comes to classes that implement IDiposable.


Throwing Exceptions


There isn’t one magic rule to throwing exceptions like there is for catching them (again, that rule is don’t catch exceptions unless you can actually handle them). Nonetheless throwing exceptions, whether or not they be your own (which we’ll cover next), is still pretty simple. First we’ll look at the actual mechanics of throwing exceptions, which relies on the throw statement. Then we’ll examine when and why you actually want to throw exceptions.


Throwing Mechanics


You can either throw a new exception, or rethrow a caught exception. To throw a new exception, simply create a new exception and throw it.

throw new Exception(“something bad happened!”);
//or
Exception ex = new Exception(“somethign bad happened”);
throw ex;

I added the second example because some developers think exceptions are some special/unique case – but the truth is that they are just like any other object (except they inherit from System.Exception which in turn inherits from System.Object). In fact, just because you create a new exception doesn’t mean you have to throw it – although you probably always would.


On occasion you’ll need to rethrow an exception because, while you can’t handle the exception, you still need to execute some code when an exception occurs. The most common example is having to rollback a transaction on failure:

ITransaction transaction = null;
try
{
transaction = session.BeginTransaction();
// do some work
transaction.Commit();
}
catch
{
if (transaction != null) { transaction.Rollback(); }
throw;
}
finally
{
//cleanup
}

In the above example our vanilla throw statement makes our catch transparent. That is, a handler up the chain of execution won’t have any indication that we caught the exception. In most cases, this is what we want – rolling back our transaction really doesn’t help anyone else handle the exception. However, there’s a way to rethrow an exception which will make it look like the exception occurred within our code:

catch (HibernateException ex)
{
if (transaction != null) { transaction.Rollback(); }
throw ex;
}

By explicitly rethrowing the exception, the stack trace is modified so that the rethrowing line appears to be the source. This is almost always certainly a bad idea, as vital information is lost. So be careful how you rethrow exceptions – the difference is subtle but important.


If you find yourself in a situation where you think you want to rethrow an exception with your handler as the source, a better approach is to use a nested exception:

catch (HibernateException ex)
{
if (transaction != null) { transaction.Rollback(); }
throw new Exception(“Email already in use”, ex);
}

This way the original stack trace is still accessible via the InnerException property exposed by all exceptions.


When To Throw Exceptions


It’s important to know how to throw exceptions. A far more interesting topic though is when and why you should throw them. Having someone else’s unruly code bring down your application is one thing. Writing your own code that’ll do the same thing just seems plain silly. However, a good developer isn’t afraid to judicially use exceptions.


There are actually two levels of thought on how exceptions should be used. The first level, which is universally accepted, is that you shouldn’t hesitate to raise an exception whenever a truly exceptional situation occurs. My favorite example is the parsing of configuration files. Many developers generously use default values for any invalid entries. This is ok in some cases, but in others it can put the system in an unreliable or unexpected state. Another example might be a Facebook application that gets an unexpected result from an API call. You could ignore the error, or you could raise an exception, log it (so that you can fix it, since the API might have changed) and present a helpful message to your users.


The other belief is that exceptions shouldn’t just be reserved for exceptional situations, but for any situation in which the expected behavior cannot be executed. This approach is related to the design by contract approach – a methodology that I’m adopting more and more every day. Essentially, if the SaveUser method isn’t able to save the user, it should throw an exception.


In languages such as C#, VB.NET and Java, which don’t support design by contract mechanism, this approach can have mixed results. A Hashtable returns null when a key isn’t found, but a Dictionary throws an exception – the unpredictable behavior sucks (if you’re curious why they work differently check out Brad Abrams blog post). There’s also a line between what constitutes control flow and what’s considered exceptional. Exceptions shouldn’t be used to control an if/else-like logic, but the bigger a part they play in a library, the more likely programmers will use them as such (the int.Parse method is a good example of this).


Generally speaking, I find it easy to decide what should and shouldn’t throw an exception. I generally ask myself questions like:
1 – Is this exceptional,
2 – Is this expected,
3 – Can I continue doing something meaningful at this point and
4 – Is this something I should be made aware of so I can fix it, or at least give it a second look


Perhaps the most important thing to do when throwing exceptions, or dealing with exceptions in general, is to think about the user. The vast majority of users are naive compared to programmers and can easily panic when presented with error messages. Jeff Atwood recently blogged about the importance of crashing responsibly.:
1 – It is not the user’s job to tell you about errors in your software!
2 – Don’t expose users to the default screen of death.
3 – Have a detailed public record of your application’s errors.


It’s probably safe to say that Windows’ Blue Screen of Death is exactly the type of error message users shouldn’t be exposed to (and don’t think just because the bar has been set so low that it’s ok to be as lazy).


Creating Custom Exceptions


One of the most overlooked aspect of domain driven design are custom exceptions. Exceptions play a serious part of any business domain, so any serious attempt at modeling a business domain in code must include custom exceptions. This is especially true if you believe that exceptions should be used whenever a method fails to do what it says it will. If a workflow state is invalid it makes sense to throw your own custom WorkflowException exception and even attach some specific information to it which might not only help you identify a potential bug, but can also be used to present meaningful information to the user.


Many of the exceptions I create are nothing more than marker exceptions – that is, they extend the base System.Exception class and don’t provide further implementation. I liken this to marker interfaces (or marker attributes), such as the INamingContainer interface. These are particularly useful in allowing you to avoid swallowing exceptions. Take the following code as an example. If the Save() method doesn’t throw a custom exception when validation fails, we really have little choice but to swallow all exceptions:

try
{
user.Save();
catch
{
Error.Text = user.GetErrors();
Error.Visible = true;
}
//versus
try
{
user.Save();
}
catch(ValidationException ex)
{
Error.Text = ex.GetValidationMessage();
Error.Visible = true;
}

The above example also shows how we can extend exceptions to provide further custom behavior specifically related to our exceptions. This can be as simple as an ErrorCode, to more complex information such as a PermissionException which exposes the user’s permission and the missing required permission.


Of course, not all exceptions are tied to the domain. It’s common to see more operational-oriented exceptions. If you rely on a web service which returns an error code, you may very wrap that into your own custom exception to halt execution (remember, fail fast) and leverage your logging infrastructure.


Actually creating a custom exception is a two step process. First (and technically this is all you really need) create a class, with a meaningful name, which inherits from System.Exception.

public class UpgradeException : Exception
{
}

You should go the extra step and mark your class with the SerializeAttribute and always provide at least 4 constructors:
1 – public YourException()
2 – public YourException(string message)
3 – public YourException(string message, Exception innerException)
4 – protected YourException(SerializationInfo info, StreamingContext context)


The first three allow your exception to be used in an expected manner. The fourth is used to support serialization incase .NET needs to serialize your exception – which means you should also implement the GetObjectData method. The purpose of support serialization is in the case where you have custom properties, which you’d like to have survive being serialized/deserialize. Here’s the complete example:

[Serializable]
public class UpgradeException: Exception
{
private int _upgradeId;
public int UpgradeId { get { return _upgradeId; } }

public UpgradeException(int upgradeId)
{
_upgradeId = upgradeId;
}
public UpgradeException(int upgradeId, string message, Exception inner) : base(message, innerException)
{
_upgradeId = upgradeId;
}
public UpgradeException(int upgradeId, string message) : base(message)
{
_upgradeId = upgradeId;
}
protected UpgradeException(SerializationInfo info, StreamingContext c) : base(info, c)
{
if (info != null)
{
_upgradeId = i.GetInt32(“upgradeId”);
}
}
public override void GetObjectData(SerializationInfo i, StreamingContext c)
{
if (i != null)
{
info.AddValue(“upgradeId”, _upgradeId);
}
}


Conclusion


It can take quite a fundamental shift in perspective to appreciate everything exceptions have to offer. Exceptions aren’t something to be feared or protected against, but rather vital information about the health of your system. Don’t swallow exceptions. Don’t catch exceptions unless you can actually handle them. Equally important is to make use of built-in, or your own exceptions when unexpected things happen within your code. You may even expand this pattern for any method that fails to do what it says it will. Finally, exceptions are a part of the business you are modeling. As such, exceptions aren’t only useful for operational purposes but should also be part of your overall domain model.

This entry was posted in Foundations. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

14 Responses to Foundations of Programming – pt 8 – Back to Basics: Exceptions

  1. Burns says:

    Thanks Karl,

    It simply alerts the user that the data is not available. It’s in response to the user clicking an Update button, so the program isn’t in an unstable state, it just hasn’t been possible to update itself.

  2. karl says:

    Burns:
    That’s completely reasonable. Just follow my advice and make sure to include the inner exception in your DataNotAvailableException. This will let you debug additional problems.

    You said your caller is catching DataNotAvailableException. If you aren’t referring to the global exception handler, I must ask: can your caller actually handle having data not available?

  3. Burns says:

    What would you recommend if I have a public method that uses a HttpWebRequest to get its information, but it’s not necessarily apparent to the caller that this is happening?

    Would you let a potential WebException bubble up to the caller?

    I’m currently catching the WebExcpetion and wrapping it in my own DataNotAvailableException. Which is then caught by the caller of the method.

    Is this good or bad?

  4. OJ says:

    If you read most of the study material around the .NET framework fundamentals examination for MCPD certification, you’ll find that the general rule is to inherit from System.Exception, not System.ApplicationException. Even Transcender exams state that you should use System.Exception.

    Aside from that, not every exception makes sense to be an ApplicationException. Business logic layer and data access layer exceptions are not something I’d consider an application exception.

    Cheers :)

  5. karl says:

    @stuart:
    Thanks, fixed it.

  6. Stuart C says:

    Hi, just a small correction…you can’t access the transaction object in the catch if you intialise it in the try as it is out of scope.

  7. Martin Plotz says:

    It might be interesting for VS-users how didn’t already know: Instead of adding the [Serializable] attribute and all those constructors by hand you can simply use the “exception” snippet. Just type “excep” ->tab ->tab and you have a nice base for what you want to extend to your class

  8. karl says:

    @Jiho:
    Thanks, you’re right, I’ve made the necessary correction.

    @Dennis:
    The post covers the difference between throw and throw ex, but thanks for the link!

  9. Jiho Han says:

    Great article (and series!)

    I think your serialization constructor and GetObjectData method has been reversed. The constructor should hydrate and GetObjectData should “AddValue”.

  10. Have you tried re-throw exception with “throw;” instead of “throw ex”?

    http://www.tkachenko.com/blog/archives/000352.html

  11. Nick says:

    Other uses for exceptions.

    There are two occasions when I have used exceptions for flow control. Both are rare.

    First, inverting a matrix. Here there is a precondition on the determiner of a matrix that tells you if you can invert it. However, calculating the determiner is almost as expensive as the invert operation. Here, you try and invert and raise an exception if you can’t.

    Second case related to an ATM (augmented transition network) for parsing English. These are highly recursive, and at particular points you know what you are parsing isn’t correct. You could recurse out, with flags saying that it’s gone wrong, cleaning up as you go. Even with a code generator, the code is messy. Far better to raise an exception and handle it.

    Both cases involve clean up its difficulties.

    The general case in my view is not to use exceptions.

    It should be

    if x >= 0 then y = sqrt (x) else handle error.

    The exceptions remain as true exceptions, no the expected.

  12. karl says:

    rarour @ casey:
    Thanks for the feedback. I think the Exception vs ApplicationException debate is pretty minor, but it is nonetheless interesting. I point you guys to http://blogs.msdn.com/kcwalina/archive/2006/06/23/644822.aspx which basically says that the .NET framework itself pretty much rendered ApplicationException useless by not following its own intentions.

    Also, in my mind, the only reason to care about the base exception is if you plan on catching that type. Do you really ever plan on catching ApplicationException? Seems just as bad as swallowing Exception…Especially when you consider you could be using a 3rd party tool that throws its own ApplicationException.

  13. Casey says:

    Nice article – this is one of my pet peeves, and you have explained it really well. Personally I’m also in the “use ApplicationException, not Exception” camp along with rarous though

  14. rarous says:

    Hi, nice article. I think that custom exceptions should be derived from ApplicationException.