4.3. Commented-Out Code and Dead Code

Commenting out code so it doesn’t run is fine as a temporary measure. You might want to skip some lines to test other functionality, and commenting them out makes them easy to add back in later. But if commented-out code remains in place, it’s a complete mystery why it was removed and under what condition it might ever be needed again. Consider the following example:

doSomething() #doAnotherThing() doSomeImportantTask() doAnotherThing()

This code prompts many unanswered questions: Why was doAnother Thing() commented out? Will we ever include it again? Why wasn’t the sec- ond call to doAnotherThing() commented out? Were there originally two calls to doAnotherThing() , or was there one call that was moved after doSome ImportantTask() ? Is there a reason we shouldn’t remove the commented-out code? There are no readily available answers to these questions.

Dead code is code that is unreachable or logically can never run. For example, code inside a function but after a return statement, code in an if statement block with an always False condition, or code in a function that is never called is all dead code. To see this in practice, enter the following into the interactive shell:

>>> import random
>>> def coinFlip():
>>>
>>>     if random.randint(0, 1):
>>>
>>>         return 'Heads!'
>>>
>>>     else:
>>>
>>>         return 'Tails!'
>>>
>>>     return 'The coin landed on its edge!'
>>>
>>> print(coinFlip())
Tails!

The return ‘The coin landed on its edge!’ line is dead code because the code in the if and else blocks returns before the execution could ever reach that line. Dead code is misleading because programmers reading it assume that it’s an active part of the program when it’s effectively the same as commented-out code.

Stubs are an exception to these code smell rules. These are place- holders for future code, such as functions or classes that have yet to be implemented. In lieu of real code, a stub contains a pass statement, which does nothing. (It’s also called a no operation or no-op.) The pass statement exists so you can create stubs in places where the language syntax requires some code:

>>> def exampleFunction():
>>>
>>>     pass

When this function is called, it does nothing. Instead, it indicates that code will eventually be added in.

Alternatively, to avoid accidentally calling an unimplemented function, you can stub it with a raise NotImplementedError statement. This will immedi- ately indicate that the function isn’t yet ready to be called:

>>> def exampleFunction():
...
raise NotImplementedError
...
>>> exampleFunction()
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "<stdin>", line 2, in exampleFunction
NotImplementedError

Raising a NotImplementedError will warn you whenever your program calls a stub function or method by accident.

Commented-out code and dead code are code smells because they can mislead programmers into thinking that the code is an executable part of the program. Instead, remove them and use a version control system, such as Git or Subversion, to keep track of changes. Version control is covered in Chapter 12. With version control, you can remove the code from your pro- gram and, if needed, easily add it back in later.