16.2. 维护注释:将注释保留在代码附近

当您更改现有代码时,更改很有可能会使某些现有注释无效。修改代码时,很容易忘记更新注释,从而导致注释不再准确。不准确的注释使读者感到沮丧,如果注释太多,读者就会开始不信任所有注释。幸运的是,只要有一点纪律和一些指导规则,就可以在不付出巨大努力的情况下使注释保持最新。本节及随后的部分提出了一些特定的技术。

确保注释更新的最佳方法是将注释放置在它们描述的代码附近,以便开发人员在更改代码时可以看到它们。注释离其关联的代码越远,正确更新的可能性就越小。例如,方法接口注释的最佳位置是在代码文件中,紧靠该方法主体的位置。对方法的任何更改都将涉及此代码,因此开发人员很可能会看到接口注释,并在需要时进行更新。

对于 C 和 C ++等具有单独的代码和头文件的语言,一种替代方法是将接口注释放在.h 文件中方法声明的旁边。但是,这距离代码还有很长的路要走。开发人员在修改方法的主体时将看不到这些注释,因此需要打开其他文件并查找接口注释来更新它们,这需要额外的工作。有人可能会争辩说接口注释应该放在头文件中,以便用户可以不必看代码文件就可以学习如何使用抽象。但是,用户无需读取代码或头文件;他们应该从由 Doxygen 或 Javadoc 等工具编译的文档中获取信息。此外,许多 IDE 都会提取文档并将其呈现给用户,例如在键入方法名称时显示方法的文档。给定诸如此类的工具,文档应位于对开发人员进行代码开发最方便的位置。

在编写实现注释时,不要将整个方法的所有注释放在方法的顶部。展开它们,将每个注释推到最狭窄的范围,其中包括该注释所引用的所有代码。例如,如果一种方法具有三个主要阶段,则不要在方法的顶部写一个详细描述所有阶段的注释。而是为每个阶段编写一个单独的注释,并将该注释放置在该阶段的第一行代码的正上方。另一方面,在描述总体策略的方法实现的顶部添加注释也可能会有所帮助,例如:

//  We proceed in three phases:
//  Phase 1: Find feasible candidates
//  Phase 2: Assign each candidate a score
//  Phase 3: Choose the best, and remove it

每个阶段的代码上方都可以记录其他详细信息。

通常,注释离描述的代码越远,注释应该越抽象(这减少了注释因代码更改而无效的可能性)。

When you change existing code, there’s a good chance that the changes will invalidate some of the existing comments. It’s easy to forget to update comments when you modify code, which results in comments that are no longer accurate. Inaccurate comments are frustrating to readers, and if there are very many of them, readers begin to distrust all of the comments. Fortunately, with a little discipline and a couple of guiding rules, it’s possible to keep comments up-to-date without a huge effort. This section and the following ones put forth some specific techniques.

The best way to ensure that comments get updated is to position them close to the code they describe, so developers will see them when they change the code. The farther a comment is from its associated code, the less likely it is that it will be updated properly. For example, the best place for a method’s interface comment is in the code file, right next to the body of the method. Any changes to the method will involve this code, so the developer is likely to see the interface comments and update them if needed.

An alternative for languages like C and C++ that have separate code and header files, is to place the interface comments next to the method’s declaration in the .h file. However, this is a long way from the code; developers won’t see those comments when modifying the method’s body, and it takes additional work to open a different file and find the interface comments to update them. Some might argue that interface comments should go in header files so that users can learn how to use an abstraction without having to look at the code file. However, users should not need to read either code or header files; they should get their information from documentation compiled by tools such as Doxygen or Javadoc. In addition, many IDEs will extract and present documentation to users, such as by displaying a method’s documentation when the method’s name is typed. Given tools such as these, the documentation should be located in the place that is most convenient for developers working on the code.

When writing implementation comments, don’t put all the comments for an entire method at the top of the method. Spread them out, pushing each comment down to the narrowest scope that includes all of the code referred to by the comment. For example, if a method has three major phases, don’t write one comment at the top of the method that describes all of the phases in detail. Instead, write a separate comment for each phase and position that comment just above the first line of code in that phase. On the other hand, it can also be helpful to have a comment at the top of a method’s implementation that describes the overall strategy, like this:

//  We proceed in three phases:
//  Phase 1: Find feasible candidates
//  Phase 2: Assign each candidate a score
//  Phase 3: Choose the best, and remove it

Additional details can be documented just above the code for each phase.

In general, the farther a comment is from the code it describes, the more abstract it should be (this reduces the likelihood that the comment will be invalidated by code changes).