我有一个同事,他坚持认为他的代码不需要注释,这是“自文档”。

我已经审阅了他的代码,虽然它比我看到的其他人编写的代码更清晰,但我仍然不同意自文档化代码与经过注释和文档化的代码一样完整和有用。

帮我理解一下他的观点。

什么是自文档代码 它真的能取代注释良好和文档化的代码吗 在某些情况下,它是否比有良好文档和注释的代码更好 是否存在代码不可能在没有注释的情况下自文档化的例子

也许这只是我自身的局限性,但我看不出这怎么能成为一种好的练习。

这并不是一个争论——请不要提出为什么注释良好并有文档记录的代码是高优先级的原因——有很多资源都表明了这一点,但它们对我的同行来说并没有说服力。我认为我需要更全面地了解他的观点,才能说服他。如果你有必要,可以提出一个新的问题,但不要在这里争论。

另外,那些反对自我记录代码的人——这主要是为了帮助我理解自我记录代码传播者的观点(即积极的方面)。


当前回答

已经提出的观点是,评论应该捕捉意图,但我想再深入一点。

我认为对于任何一类问题,都有一个理想的(或几乎是这样的)词汇和语法来描述它,如果你只是让遇到这类问题的人来描述它们(假设那个人能清晰地思考),你就能看到它。

如果词汇和语法可以很容易地(通过定义类、方法等)映射到计算机语言的代码上,那么这些代码可以是自文档化的。此外,IMO还创建了一种特定于领域的语言。(这就是我对“陈述性”的粗略定义。)

如果不能实现这个理想,如果问题不能直接映射到计算机代码上,那么就需要将两者联系起来。在我看来,这就是评论的目的。

这样,当问题发生变化时,您就可以找到相应的代码部分进行更改。

编辑:顺便说一下,我并不支持OOP方法论,即每个名词都变成一个类,每个动词都变成一个方法。我已经看过足够多的臃肿软件了。

其他回答

Self documenting code is code that is trivially easy to understand. Variable naming goes a long way to making code self documenting, but i find the best tactic is to break any complicated logic down into tiny little chunks and refactor that information into seperate methods with verbose and informative names. Then your complicated methods become simply a list of steps to be performed. The tiny private helper methods then are documented sufficiently by their own method name and the complicated methods are documented as a sequence of abstract steps to be performed. In practice this strategy cannot always be applied perfectly so comments are still very useful. Plus you should never completely abandon any tool which will help you write code that is easier to understand.

来自非评论阵营的一些观点。

“注释良好”(冗长)的代码更难阅读和理解。首先,有更多的文本需要扫描。它增加了理解CodeBase的认知努力——非功能性文本占用了屏幕上可以用来显示代码的空间。

注释的另一个大问题是它们不可靠——尤其是在旧的代码库中,注释腐烂比位腐烂发生得更快。

当然,还有写评论的工作。除了偶尔的一行注释之外,每次我开始注释代码时,都会有两种负罪感

这个信息需要在整个支持文档中 我需要清理我的代码

在我看来,任何代码都应该是自记录的。在良好的、自文档化的代码中,您不必解释每一行,因为每个标识符(变量、方法、类)都有一个明确的语义名称。过多的注释实际上会使代码更难阅读(!),所以如果您的同事

为每个类、成员、类型和方法and编写文档注释(Doxygen、JavaDoc、XML注释等) 清楚地注释代码中没有自文档化AND的部分 为每个代码块写一个注释来解释意图,或者代码在更高抽象级别上做了什么(例如,找到所有大于10mb的文件,而不是遍历目录中的所有文件,测试文件大小是否大于10mb,如果为真则返回)

在我看来,他的代码和文档都很好。请注意,自文档化的代码并不意味着不应该有注释,而只是不应该有不必要的注释。然而,问题是,通过阅读代码(包括注释和文档注释)应该立即理解代码的功能和原因。如果“自文档化”代码比注释代码需要更长的时间来理解,那么它就不是真正的自文档化。

自文档代码是一个很容易解决的问题,随着时间的推移,代码、注释和文档会出现分歧。编写清晰的代码也是一个约束因素(如果你对自己有那么严格的话)。

对我来说,以下是我努力遵循的规则:

Code should be as easy and clear to read as possible. Comments should give reasons for design decisions I took, like: why do I use this algorithm, or limitations the code has, like: does not work when ... (this should be handled in a contract/assertion in the code) (usually within the function/procedure). Documentation should list usage (calling converntions), side effects, possible return values. It can be extracted from code using tools like jDoc or xmlDoc. It therefore usually is outside the function/procedure, but close to the code it describes.

这意味着所有三种记录代码的方法都很接近,因此更有可能在代码更改时被更改,但它们所表达的内容并不重叠。

首先,很高兴听到您同事的代码实际上比您见过的其他代码更清晰。这意味着他可能不会用“自记录”作为懒得注释代码的借口。

自文档代码是不需要自由文本注释的代码,以便知情的读者理解它在做什么。例如,这段代码是自记录的:

print "Hello, World!"

这也是:

factorial n = product [1..n]

这也是:

from BeautifulSoup import BeautifulSoup, Tag

def replace_a_href_with_span(soup):
    links = soup.findAll("a")
    for link in links:
        tag = Tag(soup, "span", [("class", "looksLikeLink")])
        tag.contents = link.contents
        link.replaceWith(tag)

现在,“知情读者”这个概念是非常主观和情境化的。如果你或其他人在遵循同事的代码方面遇到了困难,那么他最好重新评估一下他对博学读者的看法。为了调用代码自文档化,必须假定对所使用的语言和库有一定程度的熟悉。

我所见过的关于编写“自文档化代码”的最佳论据是,它避免了自由文本注释与代码编写时不一致的问题。最好的批评是,虽然代码可以描述它自己在做什么以及如何做,但它不能解释为什么某些事情会以某种方式完成。