Discussion:
[Tutor] Should error checking be duplicated for both functions if one function calls another one?
boB Stepp
2015-06-01 14:27:07 UTC
Permalink
Suppose in a given state of a program, function 1 calls function 2.
Function 1 includes checks for possible error conditions. If there are
no issues, then function 2 should execute with no issues as well. The
question is, should function 2 include the error checking done in
function 1 if function 2 is only ever called by function 1?

My inclination is to say yes, as in some future incarnation of the
program function 2 might get called in new ways. What are your
thoughts?
--
boB
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
David Palao
2015-06-01 14:33:32 UTC
Permalink
Hello,
Not sure if I got it, but, in my opinion functions should do only one
thing.So if function 2 finds an error, it should raise it. There
should be another function (function 1 in your case?) taking care of
possible raised errors.

Best
Post by boB Stepp
Suppose in a given state of a program, function 1 calls function 2.
Function 1 includes checks for possible error conditions. If there are
no issues, then function 2 should execute with no issues as well. The
question is, should function 2 include the error checking done in
function 1 if function 2 is only ever called by function 1?
My inclination is to say yes, as in some future incarnation of the
program function 2 might get called in new ways. What are your
thoughts?
--
boB
_______________________________________________
https://mail.python.org/mailman/listinfo/tutor
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
boB Stepp
2015-06-01 14:37:47 UTC
Permalink
Post by David Palao
Hello,
Not sure if I got it, but, in my opinion functions should do only one
thing.So if function 2 finds an error, it should raise it. There
should be another function (function 1 in your case?) taking care of
possible raised errors.
I guess my question was not clearly worded. The idea is that function
1 calls another function. Function 1 checks for possible errors that
are relevant. Some or all of these checks are also relevant to the
called function. Should the called function also include these
relevant error checks?

boB
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Peter Otten
2015-06-01 15:30:15 UTC
Permalink
Post by boB Stepp
Post by David Palao
Hello,
Not sure if I got it, but, in my opinion functions should do only one
thing.So if function 2 finds an error, it should raise it. There
should be another function (function 1 in your case?) taking care of
possible raised errors.
I guess my question was not clearly worded. The idea is that function
1 calls another function. Function 1 checks for possible errors that
are relevant. Some or all of these checks are also relevant to the
called function. Should the called function also include these
relevant error checks?
I think more important than not repeating the checks is that you avoid
duplicate code that does the same thing. If the checks are relatively cheap
I don't see a problem with

def check(a):
"""Verify that a ...

Helper for f1() and f2().
"""
if ...:
raise ValueError

def f1(a, b):
check(a)
c = ...
f2(a, c)

def f2(a, c):
check(a)
... # actual work

Alternatively you can make f2() private by convention:

def f1(a, b):
check(a)
c = ...
_f2(a, c)


def _f2(a, c):
"""Frobnicate a with c.

Should only be called by f1() which first verifies that
`a` cannot explode.
"""
...

Should you need a standalone version of f2() later just implement it as

def f2(a, c):
check(a)
return _f2(a, c)




_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Laura Creighton
2015-06-01 15:58:03 UTC
Permalink
How many layers do you expect your program to have? (And if the
answer is 'a whole lot' then maybe your design needs to be reconsidered.)

Dealing with the exception at the lowest level that can deal with it
is usually a good idea. Also dealing with the exception at the top level,
so that when bad things happen (i.e. the low level that was supposed to
catch it had a bug and didn't) your program doesn't terminate, but
bravely tries to do the best it can -- this often a good idea. Copy and
pasting the same wretched error handling code into every layer of
your program is pretty much never a good idea.

Laura

_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Mark Lawrence
2015-06-01 20:03:40 UTC
Permalink
Post by boB Stepp
Post by David Palao
Hello,
Not sure if I got it, but, in my opinion functions should do only one
thing.So if function 2 finds an error, it should raise it. There
should be another function (function 1 in your case?) taking care of
possible raised errors.
I guess my question was not clearly worded. The idea is that function
1 calls another function. Function 1 checks for possible errors that
are relevant. Some or all of these checks are also relevant to the
called function. Should the called function also include these
relevant error checks?
boB
No, the end result would be horrendous code bloat if that was applied
across the board. Function 2 should do the checking and raise an error
if there's a problem. Function 1 can catch that and proceed or not as
it sees fit, as can any other piece of code calling function 2. It's
the DRY principle, see http://c2.com/cgi/wiki?DontRepeatYourself
--
My fellow Pythonistas, ask not what our language can do for you, ask
what you can do for our language.

Mark Lawrence

_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Steven D'Aprano
2015-06-01 16:36:01 UTC
Permalink
Post by boB Stepp
Suppose in a given state of a program, function 1 calls function 2.
Function 1 includes checks for possible error conditions. If there are
no issues, then function 2 should execute with no issues as well. The
question is, should function 2 include the error checking done in
function 1 if function 2 is only ever called by function 1?
The answer is, "that depends".

Suppose *both* functions are public functions, which anyone can use.
Some people will call function 1 directly, some will call function 2
directly. In this case, both functions need to do their own error
checking, because they cannot trust their arguments will be correct. For
example:

def greet(name):
if name == '':
raise ValueError('you must give a name')
return "Hello " + name

def long_greet(name):
if name == '':
raise ValueError('you must give a name')
return "Greetings and salutations! " + greet(name)


Of course, if the error checking is complicated, you should factor it
out into a third function:

def greet(name):
check(name)
...

def long_greet(name):
check(name)
...



There's another possibility. Suppose that only the first function is for
public consumption, part of your library's public API. Since anyone
might use the first function, including beginners, idiots and people who
don't read the documentation, it needs to check the argument. But the
second function is only used by *you*, as an internal detail.

Of course you give the second function a name starting with an
underscore, so that others will know not to use it. (Single underscore
names are "private, don't touch".) In this case, the second function
doesn't need to check it's arguments because it can trust that the first
function will always do the right thing.

def function(arg):
if arg > 0:
return _other_function(arg)
else:
raise ValueError

def _other_function(arg):
return ...


After all, you would never make a mistake and pass the wrong value,
would you? Hmmm... perhaps we should be a little more careful...

(Note: in Python, this failure to check arguments is not as dangerous as
it may be in some other languages. You typically won't crash the
computer, or cause some horrible security vulnerability that lets
criminals or the NSA take over your computer. You will probably just get
an exception. So there are circumstances where you might choose to just
completely ignore any error checking.)

What we can do is an intermediate level of error checking between the
full checking of arguments done by public functions, and the
unconditional trust of the private function, by using assertions.
Assertions are checks which can be turned off. (Although, in truth, most
people never bother.) Our public function stays the same, and the
private one becomes:

def _other_function(arg):
assert arg > 0
return ...

If the assertion is ever false, arg is not larger than 0, Python will
raise an AssertionError exception and stop the program. You will then be
suitably embarrassed and fix the bug, before it is released to your
customers and users.

But, unlike the regular form of error checking, the assumption here is
that assertions should always pass. Since they will always pass, they
don't do anything, and can be turned off safely. You do that by running
Python with the -O (for optimize) commandline switch, which disables
asserts. This style of coding is often called "Design By Contract", and
it is a powerful system for ensuring the safety of error checking during
development and the speed of skipping unnecessary checks after
deployment.


You can read more about the use of assert here:

http://import-that.dreamwidth.org/676.html
--
Steve
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Continue reading on narkive:
Loading...