C ++中的Google样式指南。 第9部分

第1部分。简介
...
第8部分。命名
第9部分。注释
...


本文是将C ++中的Google样式指南的一部分翻译成俄语的。
原始文章 (github上的fork), 更新了翻译

留言


该代码需要注释(如果您打算阅读的话)。 以下规则描述了您应该评论的内容和方式。 但是请记住:尽管注释非常重要,但是完美的代码是自记录的。 对于类型和变量,使用“交谈”名称要好于晦涩的名称,后者需要在注释中进行描述。

根据以下读者的意见对代码进行评论:需要了解您的代码的程序员。 请记住,您可以成为下一个读者!

评论风格


使用/// * * /直到违反均匀性。

您可以使用/// ** / ,但是//是 可取的。 但是,请始终将注释样式与现有代码对齐。

文件标题中的注释


在每个文件的顶部插入许可证标头。

文件中的注释应描述其内容。 如果文件声明,描述或测试一种抽象(已经有注释),则无需在文件头中进行附加描述。 否则,请在文件顶部插入内容描述。

法律信息和作者列表


每个文件必须包含许可证信息。 描述的格式取决于项目中使用的许可证。 每个许可证(Apache 2.0,BSD,LGPL,GPL等)可能都有自己的设计要求。

如果您对该文件进行了重大更改,请考虑删除以前的作者列表。 更新的文件可能不再包含版权和作者列表。

文件内容


如果.h声明了多个抽象,则文件头中的注释通常应描述文件的内容以及抽象之间的关系。 评论中的一两个句子通常就足够了。 更详细的信息在其他位置(不在文件头中)签名。

不要在.h.cc文件中重复注释-随着时间的流逝,注释会变得不同。

类评论


每个类声明(非常明显的声明除外)都应附带注释,该类的用途以及如何使用它。

//   GargantuanTable. // : // GargantuanTableIterator* iter = table->NewIterator(); // for (iter->Seek("foo"); !iter->done(); iter->Next()) { // process(iter->key(), iter->value()); // } // delete iter; class GargantuanTableIterator { ... }; 

有关该类的注释应足以理解:如何以及何时使用该类,以及正确使用该类的其他要求。 如果需要,请描述类中的同步限制(假设)。 如果可以从不同的线程使用该类的实例,请确保写下多线程规则。

您还可以在类注释中提供简短的代码示例,以显示使用该类的难度。

通常,在不同的文件( .h.cc )中声明/定义一个类。 描述该类使用的注释应该在接口定义旁边。 关于实现的复杂性的注释应与方法本身的代码接近。

功能注释


对函数声明的注释应描述函数的使用(在最明显的情况下除外)。 有关功能定义的注释描述了实现。

功能声明


每个函数的声明应有一个注释(在声明之前),函数的功能以及如何使用它。 仅当函数很简单并且其用法很明显时(例如,减去变量值的函数),才可以省略注释。 尝试以指示性的心情开始评论(“打开文件”)。 不建议使用命令式的情绪(“打开文件”)。 注释描述的是功能的本质,而不是功能的实现方式。

在函数声明的注释中,注意以下几点:

  • 将什么输入到函数的输入中,并作为结果返回。
  • 对于类的成员函数:实例是否保留引用参数,
    我需要释放内存吗?
  • 函数是否分配调用代码应删除的内存。
  • 是否可以有nullptr参数。
  • (算法)函数的复杂性。
  • 是否可以同时允许来自不同线程的调用? 同步呢?

一个例子:

 //    .    //   .    //    GargantuanTable  . // //      . // //    : // Iterator* iter = table->NewIterator(); // iter->Seek(""); // return iter; //         , //    NewIterator()     . Iterator* GetIterator() const; 

但是,不要咀嚼明显的东西。

在记录重载函数时,请对原始函数进行主要的顽固更改。 而且,如果没有更改(经常发生),则根本不需要其他注释。

在评论构造函数和析构函数时,请记住,代码阅读器知道它们的用途。 因此,“破坏该对象”类型的注释是愚蠢的。 您可以描述构造函数的自变量(例如,更改指针的所有权)或析构函数进行的清除操作的方式。如果一切都清楚,则不要发表评论。 通常,析构函数通常没有注释(声明时)。

功能定义


如果在函数的实现中有任何技巧,可以在定义中添加解释性注释。 在其中,您可以使用代码描述技巧,概述计算的所有阶段,解释该实现或该实现的选择(特别是如果有更好的选择)。 您可以描述代码同步的原理(在这里我们进行了阻塞,但在此处进行了总结)。

请注意,您不应重复对函数声明的注释(来自.h文件等),可以简要地描述函数的作用,但主要应该是函数的作用。

变量注释


很好的方法是,变量名应立即说明其含义和原因,但是在某些情况下,还需要附加注释。

类数据成员


每个班级成员的目的应该很明显。 如果存在非显而易见的微妙之处(特殊含义,与其他成员的联系,对生存期的限制),则需要对所有这些进行评论。 但是,如果类型和名称足够,则无需添加注释。

另一方面,对特殊(非显而易见)值(nullptr或-1)的描述将很有用。 例如:

 private: //       // -1 - ,         int num_total_entries_; 

全局变量


应该注释所有全局变量的目的以及(如果不明显的话)为什么应该是全局变量,例如:

 //   ,     const int kNumTestCases = 6; 

实施意见


在非显而易见,有趣,重要的代码段的情况下,评论函数或算法的实现。

描述性评论


复杂或非标准的代码块之前应加注释。 例如:

 //    2.  x    for (int i = 0; i < result->size(); ++i) { x = (x << 8) + (*result)[i]; (*result)[i] = x >> 1; x &= 1; } 

行注释


建议用注释(通常位于行的末尾)来补充含义不明显的代码行,此注释应与代码分隔2个空格。 例如:

 //   ,    mmap_budget = max<int64>(0, mmap_budget - index_->length()); if (mmap_budget >= data_size_ && !MmapData(mmap_chunk_bytes, mlock)) return; //    

请注意,在代码块上有2条注释:一条描述了代码的作用,另一条回顾了该函数返回时错误已在日志中。

关于功能参数的评论


当为函数分配参数不明显时,请考虑以下选项:

  • 如果参数是固定值(文字常数)且该值
    用在不同的代码块中(可以理解,该值是同一件事)
    您应该创建一个常量并明确使用它。
  • 也许您应该将bool类型的参数替换为
    枚举 。 这将使论点具有自决性。
  • 对于在参数中使用多个配置选项的函数,您可以
    创建一个单独的包含所有选项的类(或结构)。 并传递功能
    该类的一个实例。
    这种方法有几个优点:选项由名称指示,这说明了
    他们的目的。 该函数中的参数数量减少了-代码更易于编写和阅读。
    而且,如果您需要添加更多选项,则不必更改函数调用本身。
  • 不要在参数中使用复杂的表达式,而应使用为其分配表达式的中间变量。
  • 作为最后的选择,请在调用位置写注释以阐明参数的目的。

请考虑以下示例:

 //    ? const DecimalNumber product = CalculateProduct(values, 7, false, nullptr); 

让我们尝试合并代码:

 ProductOptions options; options.set_precision_decimals(7); options.set_use_cache(ProductOptions::kDontUseCache); const DecimalNumber product = CalculateProduct(values, options, /*completion_callback=*/nullptr); 

不该做什么


不说明明显。 特别是,没有必要解释对了解C ++的人显而易见的事情。 相反,您可以描述此代码为什么这样做(甚至使代码自描述)。

比较:

 //    . <-- :  ! auto iter = std::find(v.begin(), v.end(), element); if (iter != v.end()) { Process(element); } 

与此:

 //  (Process) "element"     auto iter = std::find(v.begin(), v.end(), element); if (iter != v.end()) { Process(element); } 

自描述代码根本不需要注释。
对上面代码的注释通常是显而易见的(并非必需):

 if (!IsAlreadyProcessed(element)) { Process(element); } 

标点,拼写和语法


注意标点符号,拼写和语法:正确阅读书面注释要容易得多。

评论应写成故事:正确安排大写字母和标点符号。 在大多数情况下,完整的句子比短语片段更容易理解。 简短的评论(例如逐行)可能不太正式,但仍应遵循通用的风格。

尽管代码审查员过分强调使用逗号而不是分号可能会有些烦人,但保持较高的可读性和可理解性很重要。 正确的标点符号,拼写和语法可以大大促进这一点。

评论TODO


使用TODO注释作为临时代码或足够好的(中间的,不是完美的)解决方案。

注释应包括TODO行(所有大写字母),后跟名称,电子邮件地址,缺陷ID或其他信息,以识别开发人员和TODO所写问题的性质,此描述的目的是以后可以查找更多详细信息。并不意味着指定的程序员将解决此问题。 因此,当您创建TODO时 ,通常的名称就是您的名字。

 // TODO(kl@gmail.com):  "*"  . // TODO(Zeke)   . // TODO(bug 12345):   " ". 

如果您的TODO看起来像“让我们将来做不同的事情”,请指明一个特定的日期(“ 2005年11月更正”)或一个事件(“在所有客户端将处理XML请求时删除该代码”)。

注意事项:
-链接可能会导致手册中尚未翻译的部分。
-对一般问题的讨论最好在第1部分中进行。

Source: https://habr.com/ru/post/zh-CN480424/


All Articles