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.
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.
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.
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.
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.
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).
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With