Welcome to

Magenic Technologies Community Blog

Sign in | Join | Help

TryCatchEatAntiPattern

I've been refactoring code over the last few days and have begun to see a recurring anti-pattern to blog about; the try-catch-eat anti-pattern.  This pattern is possible in many languages (C#, C++, VB.NET, Java, Javascript, Ruby and newer T-SQL). 

It goes something like this (pseudo-C#):

try
{
   //do some work here
}
catch
{
  //eat the exception
}

The most recent example of this occurred where code was converting a C# decimal value to a double value using the decimal.ToDouble(); nevermind for a second that MSDN's documentation on the Decimal structure states:  "The conversion will not throw an exception.". :)

The fun thing about this pattern is its portability; e.g. one could can implement it in a for-loop, used nested if statements.  e.g.

if (/* some logical test; code changed to protect the guilty*/)
{
    foreach (/* some looping variables here; code changed to protect the guilty */)
    {
        try
        {
            if (/* some logical test; code changed to protect the guilty*/)
            {
                foreach (/* some looping variables here; code changed to protect the guilty */)
                {
                    try
                    {
                        if (/* some logical test; code changed to protect the guilty*/)
                        {
                            foreach (/* some looping variables here; code changed to protect the guilty */)
                            {
                                try
                                {
                                    if (/* some logical test; code changed to protect the guilty*/)
                                    {
                                        double d = decimal.ToDouble(someDecimalValue);
                                    }
                                }
                                catch (Exception) {}
                            }
                        }
                    }
                    catch (Exception) { }
                }
            }
        }
        catch (Exception) { }
    }
}

Now, to be fair, I know we all rush through from time-to-time and write poor quality code when we're under the gun. Unfortunately that was not the issue (this part of the project schedule has actually been pretty sane).


One potential exception to this is if you're writing a function in C# like IsDate, e.g.
public static bool IsDateEx(string s)
{
    try
    {
        return DateTime.Parse(s);
    }
    catch
    {
        //eat it?
    }
}
maybe you could get away with this.

If you were in .NET 2.0 you could use the TryParse method and avoid the try-catch-eat altogether:

public static bool IsDate(string s)
{
    DateTime result;
    return DateTime.TryParse(s, out result);
}

Development is a funny thing; often there are no absolute truths and we have to measure things by being better or worse (kind of like the eye doctor!). Implementing the try-catch-eat anti-pattern is a lazy development practice which leads to poor quality code and should be avoided when possible.

jk

Published Wednesday, May 16, 2007 11:13 AM by jeffk

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# re: TryCatchEatAntiPattern

Usually, yes, exceptions are for exceptional circumstances. However, I can think of a small number of cases where this pattern can actually increase code clarity. I recently wrote a console application for my current client that generates a set of files from an internal sql server database - and does so in a form that can easily be transferred to one of the clients business partners. At the end of the process, the program attempts to open Windows Explorer at the location that is the output path for the program. The last feature, opening windows explorer, is not critical to the program running at all. It is a true convenience feature that, if it does not run for some reason (say, a change in the API, lack of security permissions, or something of that nature) - it isn't worth throwing the exception. In such a case, I really could care less what exception occurs when I try to do the operation. Normally, "I don't care if this works, but give it a shot" blocks are a problem (especially when the blocks are big, or when it really does matter). They are the .NET equivalent of "On Error Resume Next" - which if you have ever had to debug one of those monstrosities, I feel your pain. That said, there are places, albiet few, where I can be a devil's advocate on this.
Wednesday, May 16, 2007 12:12 PM by Anonymous

# re: TryCatchEatAntiPattern

Swallowing exception is always a bad idea. If you want to log an exception that you didn't expect, that's fine, but it should never be swallowed; it should be rethrown, even in the case that Aaron gives. And try...catch...eat is not the equivalent of on-error-resume-next. OERN will go through all of the lines of code no matter what happens. try...catch...eat will stop at the line that threw the exception. That's different behavior (BTW turn on OERN in VB and Reflector the results - they're abhorrent ;) ).
Wednesday, May 16, 2007 2:13 PM by Jason Bock

# re: TryCatchEatAntiPattern

Jason, yes OERN is literally different - I understand that. I was talking about it from a "difficulty to debug" standpoint - as in, when you are refactoring a bunch of code that eats exceptions, especially when they are in large blocks, it is the same kind of nightmare to debug. I suppose in the case I describe I could log the exception... but honestly, this is a use case where nobody would read the log. The client requirement is "try to open windows explorer, and if it fails, regardless of why, just move on." Now, could I write code to test for possible errors - i.e. check permission to launch Windows Explorer prior to launching, check version of windows to make sure that Windows explorer is on the machine, etc. However, I think that would reduce code clarity (i.e. expressing what that snippet does) - decrease utility, since any exception I would not have been able to anticipate might get thrown and potentially stop the process. That said, I would agree that my counterexample is an unusual and strange use case. It is seldom that there is an action one would write code for that truly is a "try this, but if it does not happen, just move on" type case. I think the advice (dont eat exceptions) is good in general, especially in cases like Jeff describes where there are perfectly good alternatives (e.g. use TryParse instead of try{ int i = int.Parse(someString) } catch {})
Wednesday, May 16, 2007 3:07 PM by Anonymous

# @ Code Camp IV

Sitting in Neil Iverson's Powershell presentation right now; I need to learn A LOT more about this!

Saturday, April 05, 2008 1:52 PM by Jeff Knutson

# @ Code Camp IV

@ Code Camp IV

Monday, October 13, 2008 4:54 PM by jk

Leave a Comment

(required) 
required 
(required)