注释可用于传达代码做什么、应该做什么、不做什么、为什么存在、何时以及如何使用和不应该使用等等。
让我们对它们进行分类!
这不无聊吗?好吧,也许吧,尽管 卡尔 不这么认为。我认为这是我们讨论评论的重要下一步:
概述
将根据其内容、维护影响、位置和备选方案对不同类型的评论进行比较。
这些图标来自 新闻和杂志图标集 ,由 hevngrafix 创建。
类别
旁白
有注释说明了代码的 作用 。诸如“遍历客户列表”或“按新产品价格增加总数”之类的事情。
维护
要让这些评论增加 任何 价值,它们必须绝对是最新的。代码和注释之间的每一次转移都会很快导致混乱,并且很快就会被忽略。
地点
这些通常是内嵌注释。
使它们保持中途可维护性的唯一方法是只让它们在以下几行中引用代码。其他一切都会很快崩溃,因为没有机制可以找到引用即将更改的代码的遥远评论。
备择方案
通过编写干净的代码,叙述几乎可以变得多余。仔细的命名、透明的设计、众所周知的模式的使用等更好地解释了代码,也使其更易于维护。
人们普遍认为应该避免这些评论。只有在极少数情况下,如果使用神秘但不可避免的语言机制,它们才可能是必要的。
合同
然后是合同定义注释。它们描述了代码单元的核心抽象,它如何与其依赖项交互,以及哪些前置条件和后置条件成立。
他们还谈论代码的 作用 ,但与叙述性评论不同,他们以声明的方式进行。理想情况下,可以阅读它们 而不是 代码和测试。
维护
编写和维护履行这一承诺的评论需要决心、对细节的关注和明确的语言。
成功地这样做将大大增加注释代码的可用性。另一方面,不清楚或完全错误的评论,或者未能使合同和代码保持同步,将会在未来造成很多混乱。
与叙述不同,合约评论只描述抽象行为而不是实现细节,因此维护不那么紧张。
地点
在任何具有这些的语言中,应该使用文档注释(例如 javadoc 或 .net xml 注释 )来表达这一类别。
有明确的地方性要求。合同注释最好谈论单一的概念,并且只在绝对不可避免的情况下提及其他代码单元(例如,一种方法另一种方法)。如果可能,这仅以自动更新链接的形式发生(例如 javadoc 中的 @see )。否则,评论应避免重复信息并创建单一的事实来源。
备择方案
干净的代码和测试通常被认为是合同注释的替代方法。
测试的显着优势在于,只要它们通过,就可以保证该单元显示测试行为。对于注释,由于措辞不明确和半心半意的维护,行为和文档可能会有所不同,当然情况并非如此。
仅在代码和测试中记录的一个缺点是,自下而上地建立高层次的理解需要上下文切换并且需要时间——可能需要很多时间。如果之后不使用分析的代码,很多新获得的知识可能很快就会被遗忘。
我认为干净代码和测试的比较,以及另一方的合同评论是本次讨论中最重要的方面。我不会在这里进一步说明,但重复我之前说过的话:为什么不同时投资两者呢?
技术背景
注释可以提供技术背景并阐明单元代码 的用途 。 他们可以解释什么时候可以使用它,什么时候不能使用它,可以用它解决哪些问题,甚至可以举例说明如何做到这一点。
请注意,其中一些信息也可能是合同的一部分,但重要的是不要混淆这两个类别!契约注释做出承诺,上下文注释解释它为什么被做出以及它有什么好处。
上下文注释对于任何学习该部分代码的人来说都是非常有价值的——无论是使用它还是修改它。
维护
为了提供有用的上下文,作者必须从读者的角度看问题。如果常规盲目发生并且所有抽象和困难部分都如此明显,这可能会很困难。
与合同不同,上下文注释并不意味着取代阅读和理解代码本身——它们只是支持这一点。因此,虽然它们应该是最新的,但与代码的一些偏差是可以容忍的。
地点
防止合同和上下文评论混淆是必不可少的!因此最好不要混合使用它们,或者如果语言没有提供其他常用机制,至少将它们清楚地分开。
在 java 中,通常将它们组合为非 javadoc 块,通常在所描述的代码单元的开头。从 Java 8 开始, 新标签 @apinote 和 @implnote 也可以使用。
就其本质而言,此类注释可能不那么本地化,而是暗示其他代码单元。当然,最好将它们留在本地并为它们找到一个有意义的地方。但这不是必须的,因为它们不一定总是最新的。
备择方案
读者通常可以找到调用她正在研究的单元的生产代码或查看其测试。从这些呼叫站点获得更广泛的理解类似于从测试中理解合同:它始终是最新的,但可能是一种乏味的自下而上的方法。此外,这可能会在没有进一步区分或解释的情况下混合预期的和有问题的用例。
演示是描述一段代码的用途的好方法。但是,它们很少见,也必须维护。
历史背景
代码通常是根据某些需要非显而易见设计的规范或情况编写的。如果不是为了一些非常具体的细节,否则可能不会采用更简洁的方法。解释这种情况的文档提供了有价值的信息,以了解代码存在的 原因 。
记录历史背景的一种形式是代码注释。
维护
应始终对它们持保留态度,并以防止与其他评论混淆的形式书写。理想情况下,历史背景评论包括一些短语,如“在撰写本文时”,以强调其短暂性。如果他们清楚地陈述了他们的假设,就更容易将它们识别为过时的。
我看不出有什么理由花时间更新它们。似乎更好的办法是让它们站立,即使它们略微老化,当它们描述的环境变化太大以至于它们无用时,只需将它们删除。
地点
与提供技术背景的评论相比,这些评论甚至可能更经常地描述或引用没有自然单一位置的概念。如果同意不更新它们,这是可以容忍的。
备择方案
这些信息也可以以提交消息的形式添加到源代码管理中。这样做的好处是提交消息始终是“最新的”,因为变更集本身是不可变的。一条消息还可以涵盖跨不同文件的一组更改,这通常会派上用场。同时,这可能是一个缺点,因为必须在多个较大的消息中搜索非常局部的信息。最后,查找提交消息增加了从代码到文档的间接级别。
历史背景的另一个来源是提交相关的问题。它们可以包含许多很难在评论或提交消息中呈现的有价值的信息,例如图表、与客户的讨论、到其他来源(如 wiki)的链接等等。但是问题甚至从代码中删除得更远,并且通常涵盖更高层次的问题。
由 glynlowe 在 cc-by 2.0 下 发布 ——我改变了视野和着色。
反射
我们将评论分为以下四类:
我希望这个分类法能帮助团队决定他们是否以及如何使用评论。我们可以看到不同的种类有不同的属性,因此应该分开讨论。