如何在编写代码时不需要使用注释来提高可读性?

11

可能是重复问题:
在没有任何注释的情况下编写好的易于理解的代码是可能的吗?

在编码时,经常会听到这样的说法:如果需要注释,则意味着代码太难理解了。我同意代码应该易读,但由于“管道”和奇怪的语法,通常语言本身使得代码难以跟踪。我最常使用的语言是:

Java Mootools Ruby Erlang

有什么提示可以提供吗? 谢谢


1
能否在没有任何注释的情况下编写好的、易于理解的代码? - tangens
3
请注意,代码无法告诉您为什么以特定方式执行某项操作,只能告诉您如何执行。 - Thorbjørn Ravn Andersen
2
只有注释才能说明“为什么”是一个谬论。有时确实需要注释来解释,但通常代码本身就可以讲述整个故事。看,注释并不是坏事。但要考虑到注释的必要性可能意味着代码可以更清晰明了。 - Wayne Conrad
7个回答

26

推荐阅读:《代码整洁之道》(Robert C. Martin著)。

简而言之,你应该:

  • 使用有意义的变量/方法/类名;
  • 保持函数/方法短小;
  • 让每个类和方法只做一件事情;
  • 让每个方法中的代码处于相同的抽象层次。

不要害怕从if语句中提取出适度复杂的表达式;哪一个更容易阅读,是这样的

if (i >= 0 && (v.size() < u || d == e)) ...

或者

if (foundNewLocalMaximum()) ...

在干净的代码中,几乎不需要注释。我唯一能想到的例外情况是,如果你使用了一些晦涩难懂的语言特性(例如C++模板元编程)或算法,并在注释中提供了方法/算法来源及其实现细节的参考。

为什么其他任何类型的注释从长远来看都不太有用呢?主要原因是代码会变化,而注释往往无法与相应代码的更改同步更新。因此,过段时间后,该注释不仅毫无用处,而且具有误导性:它告诉你某些东西(实现注意事项,设计选择的推理,错误修复等),这些东西指的是已经不存在的代码版本,你不知道它是否适用于当前版本的代码。

我认为“我选择这个解决方案的原因”大多数时候不值得在代码中记录的另一个原因是,这样的注释的简短版本几乎总是像“因为我认为这是最好的方式”,或者是对例如“The C++ Programming Language, ch.5.2.1”的引用,而详细版本则可能会有三页之长。我认为,有经验的程序员通常可以很容易地看到和理解代码为什么被写成这样,而初学者甚至可能无法理解说明本身——试图涵盖每个人是不值得的。

最后,我认为单元测试比代码注释几乎总是更好的文档方法:你的单元测试相当有效地记录了你对代码的理解、假设和推理,而且你会在每次破坏它们时自动提醒自己保持它们与代码同步(前提是你确实在构建时运行它们)。


1
我完全同意代码更改时经常忽略注释。说得好! - yazzapps.com
2
推荐《代码整洁之道》,这是一本非常好的编程书籍。 - Dave Kirby
1
@MarkJ 我更喜欢编写不需要注释的代码,而不是花费额外的精力来保持它们的最新状态。 - Péter Török
1
当代码和注释不一致时,它们可能都是错误的。 - Wayne Conrad
@PéterTörök 我在想:编写清晰的代码是否会影响性能?我的意思是,在您的示例中,您使用一个函数替换了一个_几乎直接评估的条件_,该函数可能会测试该条件,然后根据结果返回true或false。这意味着,您不是直接测试条件,而是要进行函数调用,而该函数可能包含一个if语句,其中包含相同的条件,这反过来可能是_不干净_的或需要注释的。明确一点:我并不反对您的观点,只是在问。 - Overflowh
显示剩余4条评论

25

我认为,如果没有注释,通常不可能编写代码。

简而言之,代码记录了“如何”实现。而注释记录了“为什么”这样实现。

我希望注释能够说明编写代码的条件、要求或外部环境所施加的限制,更改代码会产生的影响以及其他需要注意的事项。注释包含了代码本身未包含的信息。


1
@Brian:那么,当代码发生变化时,有什么保证这些注释会相应更新呢?而告诉我为什么原始版本的代码_n_年前被编写成现在这个样子的注释有什么用处呢?因为它们通常与当前版本没有丝毫相似之处。 - Péter Török
2
@Peter 你可以通过代码审查或双人编程来保证注释得到更新。 - MarkJ
2
@Peter - 很抱歉,没有任何东西可以提供你所需的保证。你必须同时维护代码和注释。考虑到注释的上述标准,我预计代码会比注释更经常变化。 - Brian Agnew
@Brian 这就是我的观点,也正是为什么我更喜欢自注释的代码:对我来说少了很多烦恼。但这只是我的个人看法。 - Péter Török
3
@Peter:自我记录“why”的内容相当困难,如果完全做到,你最终会得到像“HashMap aConcurrentHashMapIntentionallyNotUsedHereBecauseOfTheUsagePattern”这样的变量名。 - Fredrik
显示剩余3条评论

7

代码中的注释应该告诉你为什么最初以某种方式执行操作。这并不意味着代码太难理解。


4

遵循以下最重要的事项:

  • 为您的变量、方法、类等命名有意义
  • 编写具有清晰职责的类/模块
  • 不要混淆不同级别的代码(不要在一个方法中进行位移和高级逻辑)

2
我认为为您的代码用户编写注释非常有用 - 描述类/方法/函数的作用,如何调用等。换句话说,需要记录API文档。
如果您需要为维护者注释某个方法的工作原理,那么我认为这段代码可能过于复杂。在这种情况下,应像其他人建议的那样对其进行重构,将其拆分为更简单的函数。

2

我个人认为完全没有评论和过多的评论一样糟糕。你需要找到合适的平衡点。关于使用长而详细的名称,这篇文章对我来说就已经概括了:阅读此文还应该阅读Kernighan&Pike关于使用长名称的观点。


1

你需要遵循一些规则。

  • 给实体(变量、类等)起一个可读且有意义的名称。
  • 广泛使用设计模式并相应地命名,例如如果是一个工厂,就将其命名为FooFactory
  • 代码格式要正确等。

1
如果你要使用设计模式,那么请按照规范命名。但我并不认为在Ruby中使用设计模式本身就能提高代码的可读性。 - Shadowfirebird

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接