Comments
Comments in source code are often overused. They are commonly used to describe what the code does or to mark different code sections. However, when following clean code principles the code itself should be expressive enough so that comments that describe what the code does or how it does something should not be necessary. Instead, if comments have to be used at all they should be used to explain why code is doing something.
The proper use of comments is to compensate for our failure to express ourself in code. Note the I used the word failure. I meant it. Comments are always failures.
- Robert C. Martin
Comments can lie
A good reason why comments should be avoided is that they can often be wrong or misleading, for example when a developer changes something in the code, but forgets to update a comment that explains what the code previously did.
The example below demonstrates how a simple typing error can make the documentation comment of a function misleading.
When reading the documentation comment of the function, one could believe that the code will load configuration from a file called defaults
if it can’t load it from the provided file path. However, the code tells us that the file is actually called .defaults
.
def load_config(parser: ConfigParser, config_path: str) -> list[str]:
"""
Loads configuration from a config file.
Falls back to the defaults file on fail.
"""
config = parser.read(config_path)
if not config:
config = parser.read(".defaults")
return config
Express yourself in code
Whenever you encounter a comment that describes what the following code section does, this code section can most likely be converted to a function.
input_number = input("Enter a number")
# check if input_number is a prime number
is_prime = True
for i in range(input_number):
if input_number % i == 0:
is_prime = False
break
print(input_number, "is a prime:", is_prime)
def is_prime(number):
for i in range(input_number):
if input_number % i == 0:
return False
return True
input_number = input("Enter a number")
print(input_number, "is a prime:", is_prime(input_number))
Avoid comments that don’t add value
Often comments are used, because their usage is mandated or simply because the author of the code felt the need to describe something. But often theses comments don’t add any actual value to the code. Avoid comments like this whenever you can.
class Container:
def __init__(self, logger):
# The logger associated with this container
self.logger = logger
class MyClass:
# ========== CONSTRUCTOR ==========
def __init__(self):
self.value = 0
# ========== SETTER ==========
def set_value(self, value):
self.value = value
Documentation comments
Most programming support some form of comments for functions that will be shown with the autocompletion of our editors or that can be used to generate documentation. Often organizations mandate that these comments are used on every function in a code base. But especially in private functions these comments often don’t add any value. However, in functions intended to be used by other people, these comments can be helpful by providing additional information about them.
def _is_sad(maybe_sad: str) -> bool:
"""Checks if string is sad
Args:
maybe_sad(str): a string
Returns:
bool
"""
return ":(" in maybe_sad or "T_T" in maybe_sad
def make_happy(sad_string: str) -> str:
"""Makes a sad string happy
Args:
sad_string(str): A string with sad smileys
Returns:
str
"""
if not _is_sad(sad_string):
return sad_string
return sad_string.replace(":(", ":)").replace("T_T", "^_^")
The _is_sad
function in the code sample above only serves as a utility used by the make_happy
function and will most likely never be used anywhere else. Adding a documentation comment there does not add any real value, but rather just adds another comment the developer has to keep up to date as the code base evolves over time. It is therefore safe to remove it.
def _is_sad(maybe_sad: str) -> bool:
return ":(" in maybe_sad or "T_T" in maybe_sad
def make_happy(sad_string: str) -> str:
"""Makes a sad string happy
Args:
sad_string(str): A string with sad smileys
Returns:
str
"""
if not _is_sad(sad_string):
return sad_string
return sad_string.replace(":(", ":)").replace("T_T", "^_^")
Good comments
There are of course also situations where the use of comments is perfectly fine. For example comments that why something is done the way it is or amplification comments that highlight the importance of a certain code section. Another good use of comments is to warn developers of possible bugs that may not have been solved yet. Finally, todo
comments are also fine to use to a certain extent. Of course the developers have to make sure that the todos
don’t pile up and actually get worked on.