views:

31

answers:

2

I have lots of code which is doing some data processing (in C# to be more specific). Very often the data may be only processed, if some criteria are met. Since the criteria can be rather complex, they are checked in a lazy fashion. They are not checked beforehand. Thus: If during the processing some criterion is not matching, the processing needs to be cancelled or shortcutted.

Since this can occure quite frequently and there are cases where this is considered to be nothing exceptional, I work with return values and with a pattern like:

if (string.IsNullOrEmpty(customerSecondaryAddress))
{
    LogCustomerHasNoSecondaryAddress(entry);
    return ProcessingStatus.IsProcessed;
}
ProcessSecondaryAddress(customerSecondaryAddress);
return ProcessingStatus.Continue;

I was hesitant to use Excpetions instead, because not matching criteria like in the example above is nothing exceptional. Besides it yields method signatures, which communicate quite clearly their purpose:

public ProcessingStatus WriteRecipientListFor(Customer customer)

The problem is, that I have to pass the status code around (ProcessingStatus). This is especially cumbersome, when the processing logic is quite nested. In this case I need to pass the status code up the callstack and return statements are scattered around in the code.

My questions are: Is the return value approach appropriate? Should I switch to Exceptions instead? Are there other patterns or approaches which I can use instead?

A: 

Hi,

In these cases I usually use exceptions - just because it makes it easy to stop processing in any place and doesn't clutter your code with error handling code. You shouldn't think about Exceptions as something that happens rarely, it is more appropriate to think about then as something that breaks the positive processing path. So I use them to signal a situation when it is not possible to continue processing, which is exactly your case.

It is obviously good practice to define your own exception type and catch it in a single place so that its obvious what it is used for.

Grzenio
+2  A: 

The guidelines I like are:

Return Values

  • When the purpose is to attempt to do something. TryParse, FirstOrDefault, SendAttempt work for this.
  • When the failing a criteria is not necessarily a total failure, and depending on what can get done, the calling method will need to behave differently. Enums work here.

Exceptions:

  • When a method's purpose is to achieve something (not attempt to achieve something), and it has no way to complete its task or recover from its state.

I especially use exceptions when I have a class that has properties where the status can be checked, and an operation is called when the status is in a bad state. That method isn't going to know how the calling method is going to want to fix the class's state.

Jeremy Pridemore
Completely agree. Your answer corresponds to the general idea that exceptions should be used in exceptional situations, not in situations that you can expect beforehand (like incorrect user input, or a file that doesn't exist).
Patrick