views:

481

answers:

8

What is the proper place to explain error handling in a try-catch statement? It seems like you could put explanatory comments at either the beginning of the try block or the catch block.

// Possible comment location 1
try
{   
    // real code
}
// Possible comment location 2
catch
{
    // Possible comment location 3

    // Error handling code

}
+5  A: 

I don't think it matters, at all.

I think the import thing to remember with commenting is to address why the code is the way it is and not what the code is doing, first and foremost. This is not to say you shouldn't explain complex logic in a concise comment, but the why is so much more important.

Jason Jackson
+17  A: 

I usually do the following. If there's only one exception being handled, I usually don't bother since it should be self-documenting.

try
{   
    real code // throws SomeException
    real code // throws SomeOtherException
}
catch(SomeException se)
{
    // explain your error handling choice if it's not obvious
}
catch(SomeOtherException soe)
{
    // explain your error handling choice if it's not obvious
}
Bill the Lizard
good point about self-documenting
orip
+1  A: 

I think a well written try/catch should be concise and specific. I agree with @Jason that the why is more important but equally, it is important to keep the code inside catch as concise as possible.

It would also help if you used specific exceptions to be caught. If you are using Java for example, try to catch a NullPointerException rather than a generic Exception. This should explain why the try catch exists and what you are doing to resolve it.

Sarat
+4  A: 

What about just setting up the code so it doesn't need extra comments?

try
{ 
   performDifficultAct( parameter );
}
catch (ArgumentOutOfRangeException couldNotFindArgument)
{
   // handle exception
}
catch (Exception otherUnknownException )
{
   // handle exception
}

No need to document if you can use your variable and method naming to show what is going on. No need to document if you are having to log or raise the exceptions - the logging message in the source code should be self-explanatory anyway. The only time you should need extra documentation in your code is when it is totally non-obvious what the code is doing or ther is an easy-to-miss gotcha or ambiguous step you have to add that will need explanation for anyone looking at the code in future.

Edit: To clarify a little, here's a bit more of how I might use those "catch" statements to provide useful information both to a maintenance programmer and to users/support/QA/anyone else who uses the software. Also an illustration of the kind of situation where I absolutely would want to add extra comments in the code:

public void PerformSomeActionOrOther(string parameter)
{
  try
  { 
     // For some reason an eleven character string causes a bluescreen from Kernel32
     if (parameter.Length==11) parameter+=" ";

     performDifficultAct( parameter );
  }
  catch (ArgumentOutOfRangeException couldNotFindArgument)
  {
     this.Log.WriteLn("Argument out of range exception in ArbitraryClass.PerformSomeActionOrOther");
     this.Log.WriteLn(String.Format("Probable cause is that {0} is not in the array", parameter));
     this.Log.WriteLn(String.Format("Exception: {0}", couldNotFindArgument.Message));
  }
  catch (Exception otherUnknownException )
  {
     this.Log.WriteLn("Unexpected exception in ArbitraryClass.PerformSomeActionOrOther");
     this.Log.WriteLn(String.Format("Exception: {0}", otherUnknownException.Message));
     throw( otherUnknownException );
  }
}
glenatron
"couldNotFindArgument" is not enough. I want to see "If this error occurs, check the table FooConfiguration".
Jonathan Allen
that's when you call off to an appropriately named method in the catch block (if the code is too complex to be self-explanatory). Commenting should be reserved for explaining blocks of code that are difficult to understand, and if it's difficult to understand, it needs to be refactored.
Michael Meadows
The comment in this case is aimed directly at the developer, asking him to do something. What's the point of creating some indirect message to the developer via method naming?
RoadWarrior
If a block of code can't be understood on its own, then the method is too complex. Comments tend to be a crutch that bad developers use because they don't know what else to do with a code smell. At a minimum, a new method is merited, but sometimes the refactoring needs to be more significant.
Michael Meadows
This has nothing to do with understanding a block of code, or about complex code. It's about delivering a clear message directly to the maintenance developer. A comment is perfect for this.
RoadWarrior
A comment is perfect for this if your code is ambiguous less so you are writing clear code. Sometimes it is necessary to explain why something has happened, but very often you will want to log that anyway, why comment it in the code where it is potentially less useful than passing it to the log?
glenatron
How many times have you gone into mature code and scratched your head at completely outdated and irrelevant comments. Maintenance programmers are usually bad at maintaining comments, so why make them do it in the first place. Self-descriptive code solves the problem.
Michael Meadows
It's relatively rare for me to find outdated or irrelevant comments. But it's quite common for me to find almost no comments, which is very annoying. Perhaps this is because I'm an author, and writing and reading is as much a part of my craft as programming.
RoadWarrior
+9  A: 

"A comment is a lie". Work on those variable names and the general logic so you can avoid it. And if you really need to lie, do it inside the catch block.

krosenvold
Nice sound bite.
Jay Bazuzi
Variable names don't tell you why something is the way it is.
Jonathan Allen
In this case, the exception class name is usually pretty clear. You probably only need the comment if you're *gasp* catching a general Exception.
Outlaw Programmer
Grauenwolf, IMO if you're doing things correctly there is no reason for "why." "Why" is for crappy hacks and workarounds.
Sara Chipps
Sarah, "why" a developer did something one way and not another is extremely important. For example, why do I use byte rather than bool for P/Invoke parameters? Because bool won't work on 64-bit Windows. Without a comment, how are you going to know why I did this?
RoadWarrior
You bring up a great point, RW, while rare things do need to be explained I feel that lots of times commenting these things doesn't allow for developers to learn what they need to learn by actually reading code. I know that we can't know everything, but I have found those situations extremely rare.
Sara Chipps
My comment-to-code ratio is about 1:5, so not rare at all. Maybe I ought to ask my employer to revoke my Distinguished Engineer award :-)
RoadWarrior
RoadWarrior: Maybe you're working in a less clean development environment. The question is tagged C# and 20% comments in C# code seems way over the top.
krosenvold
Check the code in the section marked "Check assembly's strong name signature hasn't been hacked" at this link: http://sleeksoft.co.uk/public/techblog/articles/20050621_1.html. It would be good to know which comments could be removed.
RoadWarrior
@RoadWarrior I'd say *well over* half the comments look like they could be removed if you worked more on the code and less on the comments. You are basically rephrasing your code as english in comments. I know how to read code, it doesn't scare me. Read Kent Beck on code style - he's king.
krosenvold
We'll have to agree to disagree. I write a lot of comments, and I don't suspect that's going to change in the future.
RoadWarrior
+1  A: 

The location does not matter as long as you are consistent. My personal preference is as follows:

//comment 1: code does XYZ, can cause exceptions A, B, C
try {
    //do something
}
//comment 2: exception A occurs when foo != bar
catch (ExceptionA a) {
    //do something
}
//comment 3: exception B occurs when bar is null
catch (ExceptionB b) {
    //do something
}
//comment 4: exception B occurs when foo is null
catch (ExceptionC c) {
    //do something
}
Elie
+2  A: 

Definitely don't comment the top of it, because what can you usefully say except "starting an exception handling block here"? Comments on the catch statements are better, but in general, again, what are you gonna say? "Handle a NullPointerException"?

I'd go for a comment IFF you need to say that you're doing something exciting, like chaining to an application-domain exception.

Charlie Martin
A: 

I know this isn't the answer you're looking for, but don't comment at all. If your code isn't clear enough to stand on its own without commenting, then you should refactor it until it is. Jeffrey Palermo just wrote a blog post that states it best.

Typically, comments tend to document either:

  • Code that's too compact. Things that look like this: ++i?--g:h-i;
  • Long blocks of code that need to be summarized
  • Code that is either disposable or has no clear reason for existing

See below for a simplified example of some simple commenting on your exception block, and a version that eliminates the need for comments.

bool retries = 0;
while (retries < MAX_RETRIES)
{
    try
    {
        ... database access code
        break;
    }
    // If under max retries, log and increment, otherwise rethrow
    catch (SqlException e)
    {
        logger.LogWarning(e);
        if (++retries >= MAX_RETRIES)
        {
            throw new MaxRetriesException(MAX_RETRIES, e);
        }
    }
    // Can't retry.  Log error and rethrow.
    catch (ApplicationException e)
    {
        logger.LogError(e);
        throw;
    }
}

While the above comments promote reusability, you essentially have to maintain both the code and the comments. It is possible (and preferable) to refactor this so that it is clearer without comments.

bool retries = 0;
while (canRetry(retries))
{
    try
    {
        ... database access code
        break;
    }
    catch (SqlException e)
    {
        logger.LogWarning(e);
        retries = incrementRetriesOrThrowIfMaxReached(retries, e);
    }
    catch (ApplicationException e)
    {
        logger.LogError(e);
        throw;
    }
}

...

private void incrementRetriesOrThrowIfMaxReached(int retries, Exception e)
{
    if (++retries >= MAX_RETRIES)
        throw new MaxRetriesException(MAX_RETRIES, e);

    return retries;
}

private bool canRetry(int retries)
{
    return retries < MAX_RETRIES;
}

The latter example may seem like more code for a very subtle benefit, but the gains can't be overstated. The code is just as understandable, but you have the benefit that you don't need to have a separate set of metadata (comments) in order to explain the code. The code explains itself. If your catch code block is too long and needs comment to summarize, think about refactoring it to a separate method in order to improve readability.

Michael Meadows