08 December 2015

Exception handling is now kind of a must-have feature for any ambitious programming language. But, why it is so popular? Why not just check return values?

It's Easier to Ask Forgiveness than Permission (i.e. Look Before You Leap, LBYL).

(NOTE: To demonstrate general situations, I do not use python specific features in this discussion.)

Sometimes there is no return value available to indicate errors

Compare the following:

integer = my_str_2_int(input_string) # set global var: error_no

if error_no != 0:
    handle_error
# ...
try:
    integer = int (input_string)
    # ...
except ValueError:
    handle_error

Sometimes we can do nothing at the spot of error

Compare the following code snippets

 1: def f1():
 2:     if do_some_thing:
 3:         return True
 4:     else:
 5:         return False
 6: 
 7: def f2():
 8:     # ...
 9:     if ! f1():
10:         return False
11:     # ...
12: 
13: def f3():
14:     # ...
15:     if ! f2():
16:         return False
17:     # ...
18: 
19: def f4():
20:     # ...
21:     if ! f3():
22:         handle()                # where to get the error info?
23:     # ...
 1: def f1():
 2:     if do_some_thing:
 3:         return True
 4:     else:
 5:         raise Except1(info_of_error)
 6: 
 7: def f2():
 8:     # ...
 9:     f1()
10:     # ...
11: 
12: def f3():
13:     # ...
14:     f2()
15:     # ...
16: 
17: def f4():
18:     # ...
19:     try:
20:         f3()
21:     except Except1 as exc:
22:         handle(exc)
23:     # ...

Checking return value is not always good

  • It can be tedious
  • It may bury normal call flow into error handling code.

Compare the following two code snippets

var1 = f1()
if var1 == None:
    handle_error_1

var2 = f2(var1)
if is_invalid(var2):
    handle_error_2

var3 = f3(var2)
if var3 == None:
    handle_error_3

var4 = f4(var4)
if var4 == None:
    handle_error_4
# ...
try:
    f4(f3(f2(f1())))
except Exp1:
    handle_error_1
except Exp2:
    handle_error_2
except Exp3:
    handle_error_3
except Exp4:
    handle_error_4
# ...

People forget to check return values but not exception handling

f2(f1())
  • If f1 return an invalid value, f2 use that value silently as if it is a valid and may eventually bring us big surprise.
  • If f1 raise an exception, the application abort right away (unless that exception is handled in an outer function).


blog comments powered by Disqus