注释 (Commenting)

虽然写注释很痛苦, 但是对于保持代码可读非常重要
下面的规则描述了你应该怎么写注释, 以及写在哪里。
但是记住:注释虽然非常重要, 但是最好的注释是代码本身。
直观的变量名本身就是注释, 比起起一个奇怪的名字,然后用注释解释要好得多

当写注释时,为你的观众去写:下一个贡献者需要理解你的代码。
请慷慨一些 - 下一个可能就是你自己!

—[Google C++ 风格指南][google-c++]

这一部分的指南从 Google
[C++][google-c++-comments] 和 [Python][google-python-comments] 风格指南那边借鉴了很多。

文件/类 级别的注释 (File/class-level comments)

每个类的定义都应该带些注释, 说明它是干什么的, 以及怎么用它。

如果文件里没有任何 class, 或者多于一个 class, 顶部应该有注释说明里面是什么。

  1. # Automatic conversion of one locale to another where it is possible, like
  2. # American to British English.
  3. module Translation
  4. # Class for converting between text between similar locales.
  5. # Right now only conversion between American English -> British, Canadian,
  6. # Australian, New Zealand variations is provided.
  7. class PrimAndProper
  8. def initialize
  9. @converters = { :en => { :"en-AU" => AmericanToAustralian.new,
  10. :"en-CA" => AmericanToCanadian.new,
  11. :"en-GB" => AmericanToBritish.new,
  12. :"en-NZ" => AmericanToKiwi.new,
  13. } }
  14. end
  15. ...
  16. # Applies transforms to American English that are common to
  17. # variants of all other English colonies.
  18. class AmericanToColonial
  19. ...
  20. end
  21. # Converts American to British English.
  22. # In addition to general Colonial English variations, changes "apartment"
  23. # to "flat".
  24. class AmericanToBritish < AmericanToColonial
  25. ...
  26. end

所有文件,包括数据和配置文件,都应该有文件级别(file-level)的注释。

  1. # List of American-to-British spelling variants.
  2. #
  3. # This list is made with
  4. # lib/tasks/list_american_to_british_spelling_variants.rake.
  5. #
  6. # It contains words with general spelling variation patterns:
  7. # [trave]led/lled, [real]ize/ise, [flav]or/our, [cent]er/re, plus
  8. # and these extras:
  9. # learned/learnt, practices/practises, airplane/aeroplane, ...
  10. sectarianizes: sectarianises
  11. neutralization: neutralisation
  12. ...

函数注释 (Function comments)

函数声明的前面都应该有注释,描述函数是做什么的,以及怎么用。
这些注释应该是 描述性的(descriptive) 比如 (“Opens the file”)
而不是 命令式的(imperative) 比如 (“Open the file”);
注释描述这个函数,而不是告诉这个函数应该做什么。
总的来说,函数前面的注释并不负责解释函数是怎么做到它提供的功能的。
解释功能怎么实现的注释,应该零散的分布在函数内部的注释里。

每个函数都应该提到输入和输出是什么,除非碰到以下情况:

  • 不是外部可见的函数 (not externally visible)
  • 非常短 (very short)
  • 很明显 (obvious)

你喜欢什么格式都行。在 Ruby 里两种常见的格式是 TomDoc 和 YARD。
你也可以直接简洁明了的写出来,比如这样:

  1. # Returns the fallback locales for the_locale.
  2. # If opts[:exclude_default] is set, the default locale, which is otherwise
  3. # always the last one in the returned list, will be excluded.
  4. #
  5. # For example:
  6. # fallbacks_for(:"pt-BR")
  7. # => [:"pt-BR", :pt, :en]
  8. # fallbacks_for(:"pt-BR", :exclude_default => true)
  9. # => [:"pt-BR", :pt]
  10. def fallbacks_for(the_locale, opts = {})
  11. ...
  12. end

块级和行内注释 (Block and inline comments)

这个部分有点小麻烦. 如果你下次 code review 需要解释这些代码的话, 你现在就应该写注释。
复杂的操作应该把注释写在前面。
单行的不太容易理解的代码, 注释应该写在代码后面。

  1. def fallbacks_for(the_locale, opts = {})
  2. # dup() to produce an array that we can mutate.
  3. ret = @fallbacks[the_locale].dup
  4. # We make two assumptions here:
  5. # 1) There is only one default locale (that is, it has no less-specific
  6. # children).
  7. # 2) The default locale is just a language. (Like :en, and not :"en-US".)
  8. if opts[:exclude_default] &&
  9. ret.last == default_locale &&
  10. ret.last != language_from_locale(the_locale)
  11. ret.pop
  12. end
  13. ret
  14. end

在另一方面,永远不要在注释里描述代码。你要假设读代码的人对这门语言的了解比你知道的多。

相关的一个事儿:不要用块级注释,他们前面没有空格,不方便一眼认出来是注释。
[link]

  1. # 错误
  2. =begin
  3. comment line
  4. another comment line
  5. =end
  6. # 正确
  7. # comment line
  8. # another comment line

标点符号, 拼写和语法 (Punctuation, spelling, and grammar)

要注意注释里的标点符号, 拼写和语法;
注释写得好读起来也容易。

注释应该和叙述文 (narrative text) 一样易读 (readable),
有着正确的大小写和标点符号。 在很多情况下。 完整的句子比句子碎片容易读得多。
短的注释, 比如跟在代码后面的, 可以不那么正式, 但风格应该一致。

虽然在提交代码时, 别人指出你在应该用分号的地方用了逗号, 这种小事蛮折磨人的.
但重要的是源代码应该保持高度的清晰和可读. 正确的标点符号, 拼写, 和语法非常重要.

待办注释 (TODO comments)

当代码是临时解决方案,够用但是并不完美时,用 TODO 注释。

TODO 应该全大写, 然后是写这个注释的人名, 用圆括号括起来, 冒号可写可不写。
然后后面是解释需要做什么,统一 TODO 注释样式的目的是方便搜索。
括号里的人名不代表这个人负责解决这个问题, 只是说这个人知道这里要解决什么问题.
每次你写 TODO 注释的时候加上你的名字。

  1. # 错误
  2. # TODO(RS): Use proper namespacing for this constant.
  3. # 错误
  4. # TODO(drumm3rz4lyfe): Use proper namespacing for this constant.
  5. # 正确
  6. # TODO(Ringo Starr): Use proper namespacing for this constant.

注释掉的代码 (Commented-out code)

  • 注释掉的代码就不要留在代码库里了。
    [link]