Monday, May 15, 2023

JVM

Reduce technical debt by valuing comments as much as code


Comments have long occupied a distinctly secondary place in the output of developers. Comments are so secondary, and so undervalued, that in today’s code they appear infrequently except as routine copyright and licensing headers at the top of files. This is a lost opportunity because good comments that are actively maintained are one of the most effective ways of reducing technical debt—that is, they lighten the workload of future programmers who will work on the code.

Because the culture of many development organizations undervalues comments, team leads (and managers) allow comments to get out of sync with the code—thereby increasing technical debt instead of reducing it.

And because undervaluing is the rule, developers learn to blame comments rather than the culture that allows them to get out of sync with the code. This negative view is articulated by Bob Martin’s assertion that every comment represents “a failure to express yourself in code” (see Figure 1). Note that in his book Clean Code, Martin makes this curious statement and then spends 15 pages enumerating the many instances when comments are highly useful.

Oracle Java, Java Career, Java Prep, Java Learning, Java Tutorial and Materials, Java Certification, Java Guides
Figure 1. Bob Martin has strong views about comments.

Why write comments?


Comments eliminate technical debt in several ways.

Comments explain the code’s purpose. A comment at the beginning of a file explaining what functionality is found in the code removes the need to read through all methods to gather an understanding of the file. If you’re looking for a specific file, being able to read a single sentence that describes its contents greatly speeds the search. For this reason, most coding standards urge the inclusion of just such a comment in each file.

The use of keywords in file-level comments can further facilitate searching through a large codebase for specific functionality.

Javadoc comments at the beginning of classes can substitute for file-level comments. If the comments describe the class’s role in the larger project, they further aid the reader. A description of why the class is needed, if it’s not obvious, helps others understand the class’s role. And these comments are an especially useful place for presenting any unusual information in the API of the class.

Comments explain the code. Many developers have the quixotic belief that if the code is clear enough, they don’t need to use comments. This is what Bob Martin is asserting in Figure 1. It is a lovely premise that does not hold—at all. The first problem is that most developers are under great time pressure and don’t have the time to make the code so utterly clear that it requires no further comment. In fact, the far more common experience programmers have is looking at code they wrote just six months earlier and thinking “I can’t believe I wrote that!” Don’t kid yourself that you can write code so clear that it requires no comments to be understood.

Another limitation of the clear-code objection is that code explains only how a thing is done, not why it is done that way, especially if there are obvious alternatives; if the why is not evident and obvious, technical debt accrues in the absence of an explanation. Note that without such explanatory comments, code can be exceedingly difficult to maintain because no one dares to touch it, which is the very definition of technical debt.

Comments highlight the potential gotchas. Google’s Java guidelines, for example, require a comment anytime a case statement in a switch falls through to the next case. Likewise, the guidelines require noting and explaining an empty exception catch block, as well as all other items that are either potentially overlooked, not conventional, or a frowned-upon but occasionally necessary step.

Comments provide landmarks for future work. The term self-admitted technical debt refers to the TODO and FIXME comments often encountered in codebases. On the surface, these look like detritus left behind by well-meaning programmers who were subsequently occupied with other tasks. However, an interesting study on well-maintained open source projects, “An empirical study on the removal of self-admitted technical debt,” found that 74% of such entries are removed within 180 days, most often by the developers who put them there. In other words, such comments often represent useful landmarks for future work, rather than detritus.

While not specifically a countermeasure to technical debt, I use a third marker, CURR, for “current.” This is a breadcrumb of sorts that tells me where I left off coding. I often include several lines of comments containing the information I might need when resuming work. I allow only one CURR in a codebase, so if I resume work elsewhere, I convert the existing CURR to a TODO.

Oracle Java, Java Career, Java Prep, Java Learning, Java Tutorial and Materials, Java Certification, Java Guides
Figure 2. An example of excellent commenting.

The Ousterhout approach to comments


The benefits of comments in the previous scenarios cannot be denied. They reduce technical debt, and well-maintained comments also make it easier for new team members to understand the codebase without spending hours spelunking through dead ends or posing hundreds of questions to existing staff.

However, a culture of valuing comments can encourage their use for far more than remediation of technical debt.

John Ousterhout’s excellent book, “A Philosophy of Software Design,” describes best practices for large codebases; it picks up where Martin leaves off and is much more oriented towards real-world situations. Ousterhout was the designer and implementer of the Tcl language; he later cofounded Electric Cloud, a company that specialized in DevOps tools for massive codebases (that is, codebases with more than 1 million lines of code).

While Ousterhout’s book is only 175 pages, it dedicates two full chapters to comments. The first chapter replies to the most common objections to writing and valuing comments; the second focuses on refining the quality of comments.

Ousterhout’s general dictum is that comments in code should convey whatever is in the programmer’s mind that cannot be reflected accurately in the code itself. This is an excellent guideline and one that directly countermands the contention that “every comment is a failure.” The real failure is omitting clarifying and contextual information a subsequent coder might need.

Comments can also help you clarify your own thinking. More than once, as I was writing comments for a piece of code, I recognized a defect in my implementation. This is much the same sensation as describing a problem to a colleague and having the solution appear as you’re explaining the problem—a common experience. I described an extension of this benefit in a hybrid approach that takes elements from Ousterhout’s book.

When you create a class, consider using the following useful steps, which are a significant expansion of the use of comments:

◉ Write the class interface comment first.
◉ Write the interface comments and signatures of the most important public methods, but leave the method bodies empty.
◉ Write comments and declarations for the most important instance variables.
◉ Fill in the bodies of the methods, adding implementation comments as you go along.
◉ As you discover the need for more methods, write the comments before the body.

According to Ousterhout’s experience, the benefits of these steps are threefold.

◉ When the code is done, it’s properly commented and the comments are entirely up to date.
◉ The comment-first approach enables you to focus on the abstractions rather than being distracted by the implementation.
◉ The comments reveal code complexity—if a method or variable requires a long, complex comment, it probably needs to be rethought and simplified.

That’s a lot of benefits!

Of the things to comment, the most important in Ousterhout’s view are abstractions (which are difficult to tease out from reading the implementation code) and an explanation of why the code exists. In sum, a developer working on your code for the first time should be able to scan the class’s comments and have a good idea of what the class does and understand the most important implementation aspects.

If this approach appeals to you—as it does to me—Ousterhout suggests that you use it until you’re accustomed to writing code this way. He contends, and I agree, that doing so will convert you by delivering cleaner, clearer code that is fully commented.

The luxury of Javadoc


Java developers have an excellent tool for pursuing this deeper approach: Javadoc annotations. If you write code in more than one language, you’ll quickly come to realize how paltry the commenting options are in other languages. Most languages do not have any built-in counterpart to Javadoc. Or, as in the case of Go and a few other languages, if they have a counterpart, it’s threadbare by comparison.

Javadoc lets you convert comments into elegant, well-formatted, and usable documentation. And as you can see from the excellent docs in the JDK distribution, the Java team has made full use of the tool in a thoughtful, conscientious discipline. (By the way, the JVM itself is extensively commented.)

Comments in open source projects


A final note: If you’re contributing to an open source project, you should deeply value comments. One of the biggest obstacles prospective collaborators have when considering joining a project is the difficulty of learning the codebase—most often because it contains no comments (outside of the license header).

Good open source project leaders work hard at providing accessible documentation and well-commented code so that potential contributors can grok the code easily and quickly fix a small bug without excessive effort. Projects that pride themselves on good documentation and heavy commenting, such as Redis, are rewarded with good participation.

In one project I work on, Jacobin, which is a JVM written in Go, the contributors use comments extensively. Potential contributors are also provided with an additional resource: an overview of the codebase that makes it easy to understand the overall architecture of the project and how it maps to the code layout.

These steps take time, but they help the project’s contributors as much as they help the project’s intended audience by forcing Jacobin’s developers to be explicit in our assumptions, clear in our thinking, and disciplined in our work.

Conclusion


Poorly maintained comments are a clear source of technical debt. To avoid this problem, value comments as much as you do code. For example, when doing code reviews, pay particular attention not only to the comments around the new code but also to whether higher-level comments in the file are still correct in light of the new functionality.

Because the JDK bundles Javadoc, you have the unique opportunity to thoroughly benefit from disciplined appreciation of comments—thereby eliminating technical debt.

Source: oracle.com

Related Posts

0 comments:

Post a Comment