Skip to main content

The Importance of Code Comments and Documentation: A Pillar of Software Engineering

The Importance of Code Comments and Documentation: A Pillar of Software Engineering

Throughout my professional life, I have encountered thousands upon thousands of lines of code with no comments at all. A growing number of developers today believe that code comments and documentation are outdated practices, relics of an earlier era in programming. Some argue that well-written code should be self-documenting and that comments are redundant or even misleading. While there is some merit to the idea of writing expressive, clean code, the notion that comments and documentation are unnecessary is seriously flawed. It disregards one of the foundational principles of software engineering: abstraction.

Abstraction and the Role of Comments

In software engineering, abstraction is the purposeful hiding of certain details of a system in order to highlight others. According to Liskov and Guttag (2001), abstraction simplifies systems by modeling complex behaviors through simplified interfaces, making systems easier to understand and reason about. A function with a descriptive name is itself an abstraction, developers can understand what it does without diving into its implementation. For example:

def calculate_tax(income):
    # ... complex tax rules and brackets here
    return tax

The name calculate_tax tells us something about the function, but not everything. What tax rules are being applied? Is it flat-rate or progressive? What currency? Is the income pre-tax or net? Comments and documentation fill in these gaps, saving the developer from reading complicated code.

Classes, Interfaces, and the Limits of Naming

A class is also an abstraction. When a developer creates an instance of a class, they typically rely on its method names and signatures to understand what it does:

user = User(name="Alice", email="alice@example.com")
user.reset_password()

Here, reset_password() might seem self-explanatory. But what does it actually do? Does it email a temporary password? Does it trigger a two-factor authentication step? Does it check password history? Without either source code access or documentation, the developer is left guessing.

Well-placed comments (or API documentation) can answer these questions without the need to delve into implementation details:

# Sends a password reset email with a temporary login link
user.reset_password()

This is the power of documentation as an enabler of abstraction, it allows developers to trust and use interfaces without needing to understand their inner workings.

Comments as Communication

Robert C. Martin, in his seminal work Clean Code (2008), famously said, "The proper use of comments is to compensate for our failure to express ourselves in code." He acknowledges that while comments shouldn't be used to explain the obvious, they are still an essential tool for conveying the why behind the what.

Consider a more complex function:

def adjust_thresholds(metrics):
    # Skip adjustment if metrics are incomplete
    if not metrics.has_all_values():
        return
    # Normalize and smooth the values before computing new thresholds
    normalized = smooth(metrics.normalize())
    # Adjust thresholds based on 95th percentile
    compute_and_apply_thresholds(normalized)

The comments here don't just paraphrase the code—they explain intent and design choices that might not be obvious. This kind of commentary is invaluable for future maintainers or collaborators who may not know the original rationale behind specific decisions.

Everything in moderation - When to Comment and When Not To

Of course, moderation is key. Over-commenting can clutter code and reduce readability. Commenting every single line, especially when it's self-explanatory, is counterproductive:

# Add one to i
i += 1  # Redundant comment

However, complex logic, domain-specific operations, or non-obvious algorithms should always be annotated. Comments should answer questions that code alone cannot easily answer:

  • Why is this done this way?

  • What are the assumptions?

  • Are there known limitations or caveats?

A good rule of thumb is: if someone unfamiliar with the code would spend more than 10 seconds wondering "why?," it needs a comment.

Related Software Engineering Principles

In addition to abstraction, other software engineering principles support the case for comments:

  • Information Hiding (Parnas, 1972): Modules should expose only what is necessary. Comments help bridge the information gap when reading only the interface.

  • Separation of Concerns: Comments clarify boundaries and responsibilities between different parts of a system.

  • Maintainability: Readable, well-documented code is easier to maintain, refactor, and test. Studies have shown that maintainability correlates strongly with the presence of documentation.

Final Thoughts

Code is read far more often than it is written. What may be crystal clear to the author at the time of writing can be opaque six months later, (even to the original author). While clean, self-documenting code is an admirable goal, it is not a substitute for thoughtful, concise commenting and documentation.

Good comments reflect a respect for future readers of the codebase, and a commitment to long-term software quality. As the field of software engineering continues to mature, documentation remains one of its enduring pillars. It is far from being outdated!!

References

  • Liskov, B., & Guttag, J. (2001). Program Development in Java: Abstraction, Specification, and Object-Oriented Design. Addison-Wesley.

  • Martin, R. C. (2008). Clean Code: A Handbook of Agile Software Craftsmanship. Prentice Hall.

  • Parnas, D. L. (1972). "On the Criteria to Be Used in Decomposing Systems into Modules." Communications of the ACM, 15(12), 1053–1058.

Author: Dr. Sotiris Fanou