13.6. 实现注释:什么以及为什么,而不是如何

实现注释是出现在方法内部的注释,以帮助读者了解它们在内部的工作方式。大多数方法是如此简短,简单,以至于它们不需要任何实现注释:有了代码和接口注释,就很容易弄清楚方法的工作原理。

实现注释的主要目的是帮助读者理解代码在做什么(而不是代码如何工作)。一旦读者知道了代码要做什么,通常就很容易理解代码的工作原理。对于简短的方法,代码只做一件事,该问题已在其接口注释中进行了描述,因此不需要实现注释。较长的方法具有多个代码块,这些代码块作为方法的整体任务的一部分执行不同的操作。在每个主要块之前添加注释,以提供对该块的作用的高级(更抽象)描述。这是一个例子:

// Phase 1: Scan active RPCs to see if any have completed.

对于循环,在循环前加一个注释来描述每次迭代中发生的事情是有帮助的:

// Each iteration of the following loop extracts one request from
// the request message, increments the corresponding object, and
// appends a response to the response message.

请注意,此注释如何更抽象和直观地描述循环。它没有详细介绍如何从请求消息中提取请求或对象如何递增。仅对于更长或更复杂的循环才需要循环注释,在这种情况下,循环的作用可能并不明显。许多循环足够短且简单,以至于其行为已经很明显。

除了描述代码在做什么之外,实现注释还有助于解释原因。如果代码中有些棘手的方面从阅读中看不出来,则应将它们记录下来。例如,如果一个错误修复程序需要添加目的不是很明显的代码,请添加注释以说明为什么需要该代码。对于错误修复,其中有写得很好的错误报告来描述问题,该注释可以引用错误跟踪数据库中的问题,而不是重复其所有详细信息(“修复 RAM-436,与 Linux 2.4 中的设备驱动程序崩溃有关。” X”)。开发人员可以在 bug 数据库中查找更多详细信息(这是一个避免注释重复的示例,这将在 第十六章:修改现有的代码 中进行讨论)。

对于更长的方法,为一些最重要的局部变量写注释会很有帮助。但是,如果大多数局部变量具有好名字,则不需要文档。如果变量的所有用法在几行之内都是可见的,则通常无需注释即可轻松理解变量的用途。在这种情况下,可以让读者阅读代码来弄清楚变量的含义。但是,如果在大量代码中使用了该变量,则应考虑添加注释以描述该变量。在记录变量时,应关注变量表示的内容,而不是代码中如何对其进行操作。

Implementation comments are the comments that appear inside methods to help readers understand how they work internally. Most methods are so short and simple that they don’t need any implementation comments: given the code and the interface comments, it’s easy to figure out how a method works.

The main goal of implementation comments is to help readers understand what the code is doing (not how it does it). Once readers know what the code is trying to do, it’s usually easy to understand how the code works. For short methods, the code only does one thing, which is already described in its interface comment, so no implementation comments are needed. Longer methods have several blocks of code that do different things as part of the method’s overall task. Add a comment before each of the major blocks to provide a high-level (more abstract) description of what that block does. Here is an example:

// Phase 1: Scan active RPCs to see if any have completed.

For loops, it’s helpful to have a comment before the loop that describes what happens in each iteration:

// Each iteration of the following loop extracts one request from
// the request message, increments the corresponding object, and
// appends a response to the response message.

Notice how this comment describes the loop at a more abstract and intuitive level; it doesn’t go into any details about how a request is extracted from the request message or how the object is incremented. Loop comments are only needed for longer or more complex loops, where it may not be obvious what the loop is doing; many loops are short and simple enough that their behavior is already obvious.

In addition to describing what the code is doing, implementation comments are also useful to explain why. If there are tricky aspects to the code that won’t be obvious from reading it, you should document them. For example, if a bug fix requires the addition of code whose purpose isn’t totally obvious, add a comment describing why the code is needed. For bug fixes where there is a well-written bug report describing the problem, the comment can refer to the issue in the bug tracking database rather than repeating all its details (“Fixes RAM-436, related to device driver crashes in Linux 2.4.x”). Developers can look in the bug database for more details (this is an example of avoiding duplication in comments, which will be discussed in Chapter 16).

For longer methods, it can be helpful to write comments for a few of the most important local variables. However, most local variables don’t need documentation if they have good names. If all of the uses of a variable are visible within a few lines of each other, it’s usually easy to understand the variable’s purpose without a comment. In this case it’s OK to let readers read the code to figure out the meaning of the variable. However, if the variable is used over a large span of code, then you should consider adding a comment to describe the variable. When documenting variables, focus on what the variable represents, not how it is manipulated in the code.