views:

187

answers:

5

Hi,

I usually do something like the example below when I need to return error messages from a function, if no errors occur I just return an empyty string. Is this best practice, or are there alternatve ways of returning error messages from functions?

Function Test() as String
  ' Do something
  If error occured Then   
    Return "Some error message"
  Else   
    Return ""    
End Functon
+9  A: 

Instead of returning an error message you should throw an exception that contains the error message.

Here's a quick overview: http://www.vbdotnetheaven.com/UploadFile/rajeshvs/dotnetException04162005022135AM/dotnetException.aspx

Erik Engbrecht
+6  A: 

Exception Handling is the preferred method for dealing with errors. Error code return values can be obliviously ignored by developers using your functions. Exceptions force them to take notice. It's definitely worth learning about.

When you wrote the code in your question, you probably assumed that it would be called like this:

String message = Test();
// process the message for errors.

A lot of developers will just bypass processing the message, or even call your function like this:

Test();
// go about your business, happily ignoring the error message

If your code throws an exception instead, it cannot be ignored. A developer has to at least acknowledge that an exception is thrown by putting a try block around your function call. At that point they're forced to do something with it.

Bill the Lizard
A: 

I would agree that, in general, you would want to use exceptions for errors when the method would not otherwise return a value. If the method does return a value, however, you can and perhaps should use the return value in certain circumstances. For example, if you are attempting to retrieve an object from a keyed collection and the key doesn't exist, it's perfectly reasonable to return null as evidence of non-existence rather than throwing an exception. Your case doesn't seem to fit this scenario, however, and I would go with the exception.

tvanfosson
+4  A: 

As Erik and Bill have said, exceptions are the normal way of propagating errors in .NET. However, there are situations where they're not appropriate - such as validating user input. At that point there are a couple of alternatives:

  • Use an error code (e.g. an enum) to indicate the type of mistake. For instance, you might have one code for "Password was too short" and another for "Password didn't contain any numbers" etc.

  • Use an error message in the way that you've suggested in the question. I would personally use a null reference for the "it was okay" case or possibly make the method return a Boolean value (valid/invalid) and have an out parameter for the error message. Using a string is lousy for internationalisation, but is simpler in many ways (avoids extra lookups, easier to add a new kind of error etc) than the error code version. That may well be fine for an internal app which will never need to be internationalised.

I stress that these are only options where exceptions don't make sense - otherwise, exceptions are the way to go.

Jon Skeet
I know the conventional wisdom is "don't use exceptions for non-exceptional errors, like validating user input," but I find it rather dubious. Exceptions let you propagate an error through layers relatively painlessly, so you can detect and handle it where it makes sense rather than in every layer.
Erik Engbrecht
But user validation errors usually shouldn't propagate through several layers. The validation should happen once in an exception-less way at the presentation layer; deeper layers should perform validation throwing exceptions on invalid input as that indicates an error at the UI level. IMO, of course
Jon Skeet
+1 for actually addressing the original question. :) Also, congratulations on being the first to reach the 30K mark.
Bill the Lizard
If i were to use the 2nd option you mentioned, how do out parameters work?
Sean Taylor
@Sean: See http://pobox.com/~skeet/csharp/parameters.html - they're like ref parameters, but have different rules about definite assignment. @Bill: Thanks :)
Jon Skeet
@Jon if the view validates the input and then the lower layers validate their input (from the layers above such as the view) then you are very likely to end up violating the DRY principle. IMHO violating DRY requires a good reason. What's the reason behind the conventional wisdom?
Erik Engbrecht
@Erik: I can't speak for the conventional wisdom, but the UI may well work at a different abstraction. Both validations may well call common code, of course, but an exception is appropriate IMO in lower levels (where it *should* be valid) and not at the UI level where user error is to be expected.
Jon Skeet
+1  A: 

A Request-Response pattern can help with handling errors and the many ways something might fail. For example, in a credit card authentication procedure you might have:

class CreditCardAuthenticationRequest {
    string CreditCardNumber;
    string FullName;
    ...
}

class CreditCardAuthenticationResponse {
    CreditProcessorStatusCode Status;
    CreditProcessorWarnings[] Warnings;
    CreditProcessorErrors[] Errors;
    Exception Exception;
    ...
}

Now suddenly all your error handling and validation can be contained in a neat little package. The Patterns in Action sample application from DoFactory.com uses this extensively.

DavGarcia