Occasionally I’ll have a situation where I’ve written some code and, based on its logic, a certain path is impossible. For example:
activeGames = [10, 20, 30]
limit = 4
def getBestActiveGameStat():
if not activeGames: return None
return max(activeGames)
def bah():
if limit == 0: return "Limit is 0"
if len(activeGames) >= limit:
somestat = getBestActiveGameStat()
if somestat is None:
print "The universe has exploded"
#etc...
What would go in the universe exploding line? If limit is 0, then the function returns. If len(activeGames) >= limit, then there must be at least one active game, so getBestActiveGameStat() can’t return None. So, should I even check for it?
The same also happens with something like a while loop which always returns in the loop:
def hmph():
while condition:
if foo: return "yep"
doStuffToMakeFooTrue()
raise SingularityFlippedMyBitsError()
Since I “know” it’s impossible, should anything even be there?
Sometimes we make mistakes. You could have a program error now — or someone could create one later.
Those errors might result in exceptions or failed unit tests. But debugging is expensive; it’s useful to have multiple ways to detect errors.
A quickly written assert statement can express an expected invariant to human readers. And when debugging, a failed assertion can pinpoint an error quickly.
Sutter and Alexandrescu address this issue in “C++ Coding Standards.” Despite the title, their arguments and guidelines are are language agnostic.
For example, if the
defaultcase in aswitchstatement cannot occur, add the case with assert(false).