Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exceptions vs Special return values

Tags:

c#

.net

exception

Which one is a better practice in programming?

I am not talking about complete exclusivity. It's more for things like:

list<T>.Find, where you get default(T) or your value, instead of ValueNotFound exception (example).

or

list<T>.IndexOf, where you get -1 or the correct index.

like image 836
Joan Venge Avatar asked Mar 23 '09 17:03

Joan Venge


6 Answers

Well, the answer is it depends.

In the case of where an item is not found in a list, throwing an exception is a horrible practice, because it's completely feasible that the item might not be in the list.

Now if this was a specialized list of some sort, and the item should absolutely be found in the list, then that should throw an exception, because you have encountered a situation which was not feasible/reasonable.

Generally speaking, for things like business rules and the like, specialized error codes are better, because you are aware of the possibility of these things happening, and want to react to those possibilities. Exceptions are for the cases that you don't expect, and can't continue with code execution if they occur.

like image 100
casperOne Avatar answered Sep 28 '22 02:09

casperOne


I've read somewhere a nice rule about this that I like very much. It says - "a function should throw an exception if and only if it cannot perform the task it was meant to".

So what I usually do is to decide what a function should do (that usually comes from business requirements or something), and then throw exceptions for everything else.

If you have designed your application well, your functions will be pretty small and perform relatively simple tasks with simple return values. Deciding on exceptions by the above rule will not be difficult.

Of course, there are always ambiguous cases (like with a key not found in a dictionary). Those should be far and inbetween, but there you'll just have to use your gut feeling on what is the more elegant solution.

Oh, and with all this never forget: for this to work well an nice only catch exceptions that you can process. Mostly that means you will catch them only in the upper UI levels where you can display the, to the user and log them or something. Lower levels might use finally blocks or rethrow exceptions after some processing of their own, but genuine caught exceptions in low levels usually indicate bad design.

like image 34
Vilx- Avatar answered Sep 28 '22 01:09

Vilx-


A rule of thumb is to use exceptions only when something happens that "shouldn't happen".

If you would expect that a call to IndexOf() might not find the value in question (a reasonable expectation), then it should have a return code for that (probably -1 as you say). Something that should never fail, like allocating memory, should throw an exception in a failure case.

Another thing to remember is that handling exceptions is "expensive" in terms of performance. So if your code regularly handles exceptions as part of normal operations, it won't perform as fast as it could.

like image 32
JeffH Avatar answered Sep 28 '22 01:09

JeffH


In cases you mentioned I'd prefer return value as I know right there what to do with that. And there is no reason to bother with catch in the same scope.

Of course if your logic is built in a way that the values always should be in the list and their absence is the programmer logic error - exceptions are the way.

like image 34
Mykola Golubyev Avatar answered Sep 28 '22 01:09

Mykola Golubyev


You may enjoy my two-part blog series that discusses a lot of trade-offs here depending on what features your programming language supports, as it seems quite relevant:

An example of the interplay between language features and library design, part one

An example of the interplay between language features and library design, part two

I'll add that I think a lot of the answers to this question are poor (I downvoted many of my cohorts). Especially bad are APIs along the lines of

if (ItWillSucceed(...)) {
    DoIt(...)
}

which create all kinds of unhappy issues (see my blog for details).

like image 22
Brian Avatar answered Sep 28 '22 01:09

Brian


Which would you rather use?

A:

item = list.Find(x);

B:

If (list.Contains(x))
    item = list.Find(x);
else
    item = null;

C:

try {
   item = list.Find(x);
}
catch {
     item = null;
}

I'm willing to bet the answer is A. Therefore, in this case returning Default(T) is the right choice.

like image 34
Jonathan Allen Avatar answered Sep 28 '22 01:09

Jonathan Allen