Tuesday, January 20, 2009

Exceptions Revisited

Exceptions are an integral part of any modern programming language. AS a mover from Java to .Net I have had my fair share of exception handling changes. In Java you have both checked and unchecked exceptions and the throws exception clause is part of the method signature. In .Net (C#) all exceptions are unchecked which was kind of weird to me at the start. But after programming with .Net for over 2 years now I'm pretty convinced that the unchecked exceptions are the way to go. But I came across Spec#, an experimental extension language to C# by Microsoft has decided to give checked exceptions another go and thus I thought I'd revisit the whole argument again.

When the chief architect of C# language,
Anders Hejlsberg was asked why they opted to keep checked exceptions (which he recalls as 'handcuffs' on programmers ) he sighted 2 main reasons.
  1. Scalability
  2. Versioning
What he meant by scalability is the fact that when you write programmes which interacts with a whole bunch of other subsystems and APIs the number of exceptions the programmer is forced to handle grows out of control. When you just deal with the IO namespace in .Net framework this is not so much of an issue as you only have to handle a few IO exceptions but in large systems you can end up having to handle tens and hundreds of exceptions. So what happens is that the programmer gets tired of this and writes a big catch Exception clause which completely defeats the purposes of having checked exceptions in the first place. Or even worst they have the empty curly braces for each catch clause which is basically a planted time bomb. Another valid tactic people use is catching all checked exceptions and to wrap them as Runtime exceptions making sure that they no longer obstruct the users on top of the chain.

Under 'Versioning' the problem is that the throws clause is part of the method signature. So when you release a second version of an API or class library you can not introduce new exceptions or change existing ones since it will break client code. You are now left with having to declare a new method with a different set of exceptions which makes the API messy and unclean.

On the other hand one of the main arguments against unchecked exceptions is that the client programmer has to solely depend on the documentation of the API method to know what exceptions can be thrown by the function. But you can have a tool do this analysis for you like the 'Exception Hunter' from RedGate Software. According to Hejlsberg the most important thing about exceptions is not how you handle them, but how you release resource upon encountering one. This is perfectly handled by the try-finally blocks or using blocks in C# (Disposable pattern). The reason is that only a fraction of exceptions caught really need or can be handled by client code. The proven practice of dealing with unchecked exceptions is to let them propagate to the top of your call stack and handle them in a single place. By handling what is usually being done is a message to the user and graceful termination of the programme. We do this in very simple way in ASP.Net applications by using the Global.asax Application_Error handler.

Post a Comment