Digbyswift is based in Leeds, West Yorkshire offering web and digital solutions. With over a decade of experience in corporate and agency web development, Digbyswift can meet and support your requirements, whether it be MVC or web forms development, Umbraco, bespoke CMS build and maintenance, ecommerce, SEO and Google analytics or even client training. Read more ...

Exception handling – why prevention is worse than cure

By Digbyswift at June 21, 2011 14:02

I was recently made to question my use of exception handling by a programmer at a new client.

I have always been fastidious about logging errors but ultimately trying to prevent exceptions  from reaching the UI of the application. In the context of a website, I concede that sometimes unexpected exceptions occur and I can’t avoid the user being presented with a “Oopsie!” message. But my philosophy has always been to not upset the user. There are many ways to upset a user and moving the user to a new “Whoops, we did something wrong!” page would certainly upset the user.

So I would normally, try and catch errors as they happen and then handle them in some manner:

  • Log the exception as standard using Log4net;
  • Use ELMAH to catch all unhandled exceptions;
  • Return a response object that encapsulates the return value and status of the method called;
  • Do not move the user away from the page they are currently viewing but display a ‘friendly’ message instead;
  • Ensure they can not easily repeat the action that caused the exception;
  • Ensure the user cannot complete the process they are taking part in if the exception might cause further issue;
  • With the exception of mis-configuration, ensure that exceptions are not thrown across the boundaries of independent libraries;

This is what I try and do. I thought it was good practice. Well, after a little thought and a little reading it seems that although my intention is right, the implementation is wrong diddly-wrong.

An epiphany

So like I said, a programmer, Ollie, at my new client stated that in the project we would be working on together, exceptions will be allowed to bubble all the way up to the UI. I was surprised and reluctantly agreed but I did know that this approach had several merits:

  • Provided that enough time was given to testing, the application would become more robust as all exceptions would be very visible;
  • There is a reduction in code complexity as there are limited constructs, routines and general code paths for handling exceptions;
  • All exceptions are logged in exactly the same way and in one place;
  • The concept is straightforward and easy for new programmers to adopt.

I knew all this, so it made me think, why am I doing things differently in my own projects?

I realised that possibly my focus has been on “prevention rather than cure”. When I say “prevention”, I mean I have always coded in such a way that assumes that things will error and that I should prevent these errors from fucking processes up. It’s the equivalent of manufacturing a car with a second brake that kicks in just in case the first fails. The first freakin’ brake should not fail and there should not be a need for a second.

So, code should be allowed to error. I should let it error, and then fix the bug. Find more errors and fix the bugs.

Where did I go wrong?

So why do I code like this? Where does this come from?

I look back at the places I have worked and coded. With a couple of exceptions, I have always seemed to work for companies where testing is considered surplus to requirement. The kind of places where the jobs are always under-quoted and timings are under-estimated. These places are great for learning quickly, but terrible for learning correct and well thought-out implementation practices.

Of course this is no excuse, I have learnt and taught myself a lot. I could have remedied this. I have worked with many fantastic developers, one in particular Paul Lemon at MadeByPi once told me that “if I have not found any errors, there is something wrong” and this has always held true. There being no errors generally means that my exception handling is not working and not notifying of errors.

Questions?

What I need to know now is, where is the compromise? I don’t want my deploy my UI, no matter how much testing it has been through, with the knowledge that an exception will bounce the user through to a generic 500 page. I want to be able to place handling code in my UI to allow as little interruption as possible in the case of an unhandled exception, but obviously this does not fit in with the concept of allowing all exceptions to bubble up.

Do I code in this handling after testing? Wouldn’t this defeat the purpose of testing and actually require further testing?

What I do know is that I have to stop placing secondary ‘brakes’ in my code. Doing so is actually preventing me from becoming a better programmer.

log4net vs NLog

By Digbyswift at April 14, 2011 13:46

This has been covered well in this Stackoverflow article but I was explaining the importance of the differences and of the implementation to a colleague recently.

The implementation is almost identical for each:

  • Both require a configuration file;
  • Logging objects in either are created in much the same way;
  • Both have instance methods on a Logger object allowing you to log debug messages, warning messages errors etc.
private static Logger Log = LogManager.GetLogger(typeof(ThisClass));
 
public void SomeMethod()
{
    try
    {
        // some code that may fail
    }
    catch(Exception ex)
    {
        Log.Error("SomeMethod() failed", ex);
    }
}

The core difference for me though is that log4net is no longer being actively supported. It hasn’t been for years. I’ll admit, all my projects use log4net. Every one of them. But I’m considering changing.

NLog is current and seems to be moving with the goal posts and this gives me some comfort. The advantage that log4net offers is that the way I use it is so basic, i.e. class-level logging, I have to ask myself whether there is any point in changing?

The answer of course is to wrap the implementation of whichever logger is used in a facade pattern. This would allow you to use either as needs be.