Skip to content

Instantly share code, notes, and snippets.

@zedshaw
Forked from timruffles/handled elses
Last active August 29, 2015 14:05
Show Gist options
  • Save zedshaw/1d89c156c03815dcb5ad to your computer and use it in GitHub Desktop.
Save zedshaw/1d89c156c03815dcb5ad to your computer and use it in GitHub Desktop.
# Examples of various error handling mechanisms and if-statements.
def something(x,y):
if !x:
raise "argh!"
else:
if !y:
raise "oh noes!"
else:
return "Happy"
# if those aren't guards/asserts then this
def something(x, y):
if x and y:
return "Happy"
else:
raise "Oh noes!"
# if they are then this:
def something(x, y):
assert x, "You have a bad x."
assert y, "You have a bad y."
return "Happy"
# If the exception is needed, then use
# a real exception, not a string.
# chances are you don't actually need
# this though and assert works.
def something(x, y):
if !x: raise BadError("Bad x.")
if !y: raise OtherBadError("Bad y.")
return "Happy"
# If this was a really common pattern, I might do make
# a decorator and copy Design by Contract semantics.
@precond(x, "You have a bad x.")
@precond(y, "You have a bad y.")
def something(x, y):
return "Happy"
# but that's really just replicating asserts
# It's more that you are making an assert, and
# should treat it as such, not as logic. That way
# the logic for operation is easily seen without
# being fuzzed by error handling logic.
#
# The better pattern then is to confirm the
# function's parameters are correct to operate
# at the beginning, then do your logic for it
# working, handling errors as you go, then
# confirm your returning the right result
# and not violating any invariants you need.
# For example, confirming you didn't return
# None if that caused errors frequently.
# That's all easier done with asserts or a
# DbC system.
#
# Here's a *better* example of what you're
# asking:
def decider(x, y):
assert x and y, "Invalid arguments."
if x == "oranges":
if y == "grapes":
print "You have oranges and grapes."
else:
raise FruitError("Invalid fruit for y.")
elif x == "starfruit":
if y == "apples":
print "You have starfruit and apples."
else:
raise FruitError("Invalid fruit for y.")
else:
raise FruitError("Invalid fruit for x.")
# in this case the raised errors in the dangling
# else branches ensure that, should the function's
# usage change in the future to include other
# possible fruit, this will blow up and you'll have
# to go fix it for the new situation. It is effectively
# a "whitelist if" because you are saying "this only
# handles these conditions, everything else is an error."
#
# The extra advantage of this then is if you do automated
# testing you can evolve your code easily by adding the
# new fruit to the test for this, run it, and fix wherever
# it blows up. Much easier than scanning ever possible
# branch, but in more complicated functions you'd still
# need to do that.
def something(x,y):
if !x:
raise "argh!"
if !y:
raise "oh noes!"
return "Happy"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment