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

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

帮我理解一下他的观点。

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

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

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

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


当前回答

大多数文档/注释都是为了帮助未来的代码增强者/开发人员,从而使代码可维护。 通常情况下,我们会在稍后的时间回到我们的模块来添加新功能或优化。 在那个时候,通过简单地阅读注释来理解代码要比通过大量的断点来理解代码容易得多。 此外,我宁愿花时间思考新的逻辑,而不是破译现有的。

其他回答

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

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

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

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

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

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

我很惊讶居然没有人提出“识字编程”,这是一种由德克萨斯州的Donald E. Knuth在1981年提出的技术,并因《计算机编程的艺术》而闻名。

前提很简单:既然代码必须被人类理解,注释被编译器简单地扔掉,为什么不给每个人他们需要的东西——对代码意图的完整文本描述,不受编程语言要求的限制,为人类读者和编译器提供纯代码。

识字编程工具通过为文档提供特殊标记来实现这一点,这些标记告诉工具哪些部分应该是源代码,哪些部分是文本。该程序随后从文档中提取源代码部分并汇编代码文件。

我在它的网页上找到了一个例子:http://moonflare.com/code/select/select.nw或HTML版本http://moonflare.com/code/select/select.html

如果你能在图书馆找到Knuth的书(Donald E. Knuth,文学程序设计,斯坦福,加利福尼亚:语言和信息研究中心,1992,CSLI课堂笔记,没有。27.)你应该读一读。

这是自文档化的代码,包括推理等。即使是一份很好的文件, 其他一切都是写得很好的评论:-)

我认为,质疑某一行代码是否具有自文档性是有意义的,但最终,如果你不理解一段代码的结构和功能,那么大多数时候注释是没有用的。以amdfan的“正确注释”代码片段为例:

/* compute displacement with Newton's equation x = v0t + ½at^2 */
const float gravitationalForce = 9.81;
float timeInSeconds = 5;
float displacement = (1 / 2) * gravitationalForce * (timeInSeconds ^ 2);

这段代码很好,但下面的代码在大多数现代软件系统中同样具有丰富的信息,并且明确认识到使用牛顿计算是一种选择,如果其他一些物理范式更合适,可能会被改变:

const float accelerationDueToGravity = 9.81;
float timeInSeconds = 5;
float displacement = NewtonianPhysics.CalculateDisplacement(accelerationDueToGravity, timeInSeconds);

根据我个人的经验,很少有绝对需要注释的“正常”编码情况。举个例子,你有多频繁地使用自己的算法?基本上,其他一切都是构建系统的问题,以便编码器能够理解正在使用的结构以及驱动系统使用这些特定结构的选择。

我曾经和一个家伙一起工作,他打算把金融套件卖给一家大公司。他们坚持让他记录源代码,他写了一个30多页的汇编程序,并说“这是有记录的,看”——然后他翻到第13页,有一条评论“bump counter by one”。 伟大的产品,伟大的实现者,但是……

无论如何,在我看来,上面的重要评论是为了设置上下文。这段代码是自记录的:

> 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)

但是,就我个人而言,需要一个背景来充分理解它。

不管纯粹的自文档代码是否可以实现,有一些事情是人们应该做的:

Never have code that is "surprising". Ie. don't use silly macro's to redefine things etc. Don't misuse operator overloading, don't try to be smart on this. Split away code at the right point. Use proper abstractions. Instead of inlining a rolling buffer (a buffer with fixed length, with two pointers that gets items added at one end and removed at the other), use an abstraction with a proper name. Keep function complexity low. If it gets too long or complex, try to split it out into other other functions.

当实现特定的复杂算法时,添加描述算法的文档(或链接)。但在这种情况下,要努力去除不必要的复杂性,增加易读性,因为很容易犯错误。