Last Revision — April 19, 2022
3 Min Read
Comment
Dispensables
Names
Within a Class
- Fallacious Comment (family)
- Uncommunicative Name (caused)
- Magic Number (caused)
- Boolean Blindness (caused)
- Complicated Regex Expression (caused)
- Complicated Boolean Expression (caused)
- Obscured Intent (caused)
Marcel Jerzyk in thesis (2022):
"Code Smells: A Comprehensive Online Catalog and Taxonomy"
William C. Wake in book (2004):
"Refactoring Workbook"
Martin Fowler in book (1999):
"Refactoring: Improving the Design of Existing Code"
Recognizing all comments as Code Smells is controversial and raises many different opinions. For this reason, I define a concrete subcategory of comments named "What" Comments that clearly defines only these comments, which in the vast majority will hint at something smells. The rule is simple: If a comment describes what is happening in a particular code section, it is probably trying to mask some other Code Smell.
This distinction leaves room for the "Why" Comments which were already defined by Wake in 2004 and were considered helpful. Wake also notes that comments that cite non-obvious algorithms are also acceptable [1]. I wanted to mention that comments may have their places in a few more cases, such as extreme optimizations, note discussion conclusions for future reference after a code review, or some additional explanations in domain-specific knowledge.
The problem is that Comments are generally smelly, as I have mentioned. This is because they are a deodorant for other smells [2]. They may also quickly degrade with time and become another category of comments Fallacious Comments, which are a rotten, misleading subcategory of ["What" Comments].
The author sees that the code is confusing and tries to be helpful by adding explanations.
Bad docstrings, which are just duplicating everything that can be understood from the method name and parameter names & type annotations, are cluttering the code, possibly sooner or later on the first occasion, they might become Fallacious Comments.
A comment that must explain what is happening in the code indicates that it can't speak for itself, which is a strong indicator of present code smells.
"What" Comment as a Grouping Label
class Foo:
def run(...):
...
# Creating Report
vanilla_report = get_vanilla_report(...)
tweaked_report = tweaking_report(vanilla_report)
final_report = format_report(tweaked_report)
# Sending Report
send_report_to_headquarters_via_email(final_report)
send_report_to_developers_via_chat(final_report)
...
class Foo:
def run(...):
...
report = self.create_report(...)
self.send_report(report)
def create_report(self, ...):
vanilla_report = get_vanilla_report(...)
tweaked_report = tweaking_report(vanilla_report)
return format_report(tweaked_report)
def send_report(self, report):
send_report_to_headquarters_via_email(final_report)
send_report_to_developers_via_chat(final_report)
...
"What" Comment as a cover for Uncommunicative Name code smell.
def get_gross_value(p, t):
"""
params
- price: float
- tax: float
"""
...
def get_gross_value(price: float, tax: float):
...
"What" Comment as a cover for Uncommunicative Name code smell.
Example of useless comment as a docstring.
def increase_attack(self, value: int):
""" Increases attack by the given value.
params:
- value: integer
"""
self.attack += value
Example of more useful comment as a docstring.
def destroy_character(character_id: int):
"""
Removes the character from the main game world scene
if it's present, otherwise throws a warning (character
could be removed due to some other trigger event).
"""
The only counter indication for removing the docstring, would be when poor auto-documentation requirements are enforced.
def increase_attack(self, value: int):
self.attack += value