注释==代码臭味

来源:互联网 发布:通达信资金博弈源码 编辑:程序博客网 时间:2024/04/26 18:09

Comments == Code Smell

 

原文地址:

http://memeagora.blogspot.com/2008/11/comments-code-smell.html

 

I am sometimes asked about my position on code comments, and, like most things, I have strong opinions about it. Two kinds of comments exist:

有时候我会对代码注释有些疑问,自然而然的对于这些疑问我有些明确的看法。注释有2种类型:

  • JavaDoc-style comments (which encompasses JavaDoc, XMLDoc, RDoc, etc), which are designed to produce developer documentation at a high level (class and method names and what they do)

JavaDoc风格的注释(包括JavaDocXMLDocRdoc 等等),这种注释是用来为开发人员提供给高层次文档说明的(类名和方法名以及他们的作用)

  • In-line comments, generally scattered around the code to indicate a note from developer to developer

内联注释,通常环绕在代码周围,用于开发者为其他开发者给出提示。

Both kinds of comments represent different smells, each with different odors depending on the target.

这两种注释因为存在环境不同会有不同的“臭味”。

What makes comments so smelly in general? In some ways, they represent a violation of the DRY (Don't Repeat Yourself) principle, espoused by the Pragmatic Programmers. You've written the code, now you have to write about the code. In a perfect world, you'd never hove to write comments for this purpose: the code will be expressive enough that someone who reads it will understand it. Two things help achieve this result: expressive, readable languages and the composed method pattern.

通常来说,是什么让注释有“臭味”? 在某些方面,它们表示一种对DRYDon't Repeat Yourself不要重复自己)原则的违反,这个规则是被实用主义程序员所推崇的。你已经写了代码,现在你又不得不为这些代码写些什么。总而言之,你在下面这种情况下的不需要写注释:代码具有充分表达力,能够让人理解。有两种情况有助于实现这个结果:表达充分的、可读的语言和结构化函数模式。

The language makes a big difference as to the readability of the code. If you write in assembly language, you're pretty much forced to write comments; no one on earth can read the code directly. As languages have matured, you can get much closer to the ideal of self-documenting code (which was explicitly attempted in Literate Programming). Especially in the modern wave of non-ceremonious languages (like Ruby, Groovy, Scala, etc), you can craft extremely readable code. To this end, ThoughtWorks projects generally avoid the more magical features of languages (like the implicit global variables in Ruby, for example) because it hurts readability. One of the side effects of dynamic typing is outstanding method names. The method name is the only vector of information about what the method does (you can't crutch on return or parameter types), so methods tend to be named much better on the dynamic language projects upon which I've worked.

编程语言和可读性的代码有很大的差异。如果你使用汇编语言,那么你肯定会被要求写注释;在这个地球上还没有人能够直接读懂汇编代码。随着语言的成熟,你可以更容易理解“自注释”代码表示的含义(这在“文学化编程”有过明显的尝试)。特别是现代流行的动态脚本语言(例如Ruby,Groovy,Scala等等),使你能够编写具有极高可读性的代码。最终,为了避免破坏代码的可读性ThoughtWorks的工程通常避免使用编程语言特有的语法(例如Ruby语言中匿名全局变量)。特点鲜明的方法名是动态类型的一种特性。方法名只是这个方法实现功能的信息载体(你不能根据它的返回值来确定它的功能),因此我参与的动态语言工程中的方法能够被更好地命名。

The second key to readable code is not to have too much of it, especially at the method level. In Smalltalk Best Practice Patterns, Kent Beck defines composed method (which I write about extensively in The Productive Programmer). Composed method encapsulates the idea that all your methods should do one and only one thing, making them as small as possible. The side effect of this discipline leads to public methods that mainly consist of calls to a large number of very small private methods, each of which do only one thing. Composed method has lots of beneficial side effects on your code: small methods are easier to test, you end up with really low cyclomatic complexity for your methods, you discover and harvest reusable code chunks more easily, and your code is readable. This last one brings us back to the topic of comments. If you use composed method, you'll find much less need to have comments to delineate sections of code within methods (actual method calls do that), and you'll find that you use better method names.

代码的可读性的第二个关键点,特别在方法级别上,是不要让每个部分做太多的事情。在Smalltak的最佳实践模式中,Kentucky Beck定义了composed methods组合方法(我在The Productive Programmer中已经做了大量的介绍了)。组合方法的思想是你所有的方法中每个方法应该做也只能做一种事情,尽量使他们短小精悍。这种思想的好处是调用的公用方法是由许多个短小的、每个只完成一种功能的大量的私有函数组成的。组合方法对你的代码有很多好处:短小的代码容易测试、函数方法的代码复杂度很低、能够更容易的获取和复用代码块、代码更易读。最后的一个好处也是注释的特点。如果使用组合方法,你会发现:不需要太多的注释来描述方法的代码段(实际上函数方法要求有注释),而且你能更好地命名函数。

Now let's talk about how this applies to the two types of comments. First, where are comments indeed useful (and less smelly)? If you are writing an API, you need some level of generated documentation so that people can use your API. JavaDoc style comments do this job well because they are generated from code and have a fighting chance of staying in sync with the actual code. However, tests make much better documentation than comments. Comments always lie (maybe not now, but on a long enough timeline, all comments will become outdated). Tests can't lie or they fail. When I'm looking at work in progress on projects, I always go to the tests first. The comments may or may not be there, but the tests define what's now done and working.

现在让我们讨论这两种注释方法适用于在哪些地方。首先,注释在哪些情况下有用(“臭味”更少)?如果你在编写API,你需要有某种的自动生成的文档供人们使用。JavaDoc风格的注释因为是从代码中自动生成的,而且能够很容易(fighting chance of)的源代码保持同步,所以这种注释符合这个目的。然而,测试能够比注释提供更好的说明。注释总是在说谎(或许现在没有,但是在一段足够长的时间之后,所有的注释都会过时的),测试却不会。在接收一个项目时,我总会测试先行的。因为注释可能没有写,但是测试能够说明这段代码现在可以做什么。

We were on a project where the client insisted on Javadoc comments for every public class and method. We started the project adding those comments, but eventually stopped. When doing agile development, you don't want anything that hampers refactoring. Having comments in place caused a dilemma: do I refactor the method and change the comment (the most work), refactor the method and leave the old comment (with the theory being that I'll change it again later, and would rather just have to update the comment once), or not refactor? No good options here. Having pervasive comments discourages refactoring because it adds significant extra friction. On this project, we abandoned commenting as we went along. The last week of the project we literally did nothing but go back and add comments to the code, which worked well because the code base had settled down by that point. But notice what's lurking in wait: the client wanted all the comments there to make it easier to maintain in the future. But who's to say that whoever maintains that code will keep the comments up to date? You have the same DRY violation as before. If they maintain the tests, they have to change as code changes because they are executable.

我们曾经做一个项目:客户坚持要为每一个公用类和方法写注释。我们在项目的开始阶段添加了那些注释,但是最终没有坚持下去。当进行敏捷开发的时候,你不希望出现任何阻碍重构的事情。有注释的地方却导致我们左右为难:我应该重构方法并且修改注释(这部分工作占用大多数工作量),或者重构方法不修改注释(以后再一劳永逸的修改这些注释),或者是不重构代码?没有好的解决办法。大量的注释在重构时的冲突导致重构工作很困难。在这个项目中,随着工作的继续,我们放弃了注释。在项目的最后一周我们的工作只是为代码填写注释,因为在那个时候代码已经确定,所以这种方法很好。但是要注意潜在的事情:客户要求代码注释是为了以后的更容易的维护系统。但是有人能够保证在代码维护之后会保持注释的同步更新吗?你也会有类似上面的DRY冲突。如果他们维护的是测试代码而不是注释文档,那么因为测试代码的可执行性,他们肯定会保证测试代码和项目代码的同步更新。

The new wave of Behavior Driven Development tools (like JBehave, RSpec, and easyb) make this "executable specification" style of comment + test feasible. I expect to see the usage of these tools skyrocket because they give you documentation that has a fighting chance of staying up to date.

新的Behavior Driven Development工具(如JBehaveRSpeceasyb)使注释+测试风格的“可执行的注释说明”成为可能。因为这些工具能够保证代码和注释说明的同步,我希望看到他们被大量的使用。

Inline comments are almost always a smell. The only legitimate use of inline comments is when you have some very complex algorithm that you need to have some thoughts about beside the code. Otherwise, the presence of inline comments indicates that you've written code that needs explanation, meaning that it cries out for refactoring. I frequently troll code bases upon which I'm working to look for inline comments so that I can refactor the code to eliminate the need for them.

内联的注释总是会有“味道”的。唯一需要使用内联注释是在你编写了非常复杂的算法,你需要在代码旁边记录说明你的想法。否则,内联注释的出现表明你写的代码需要解释说明,意味着这些代码需要被重构。我经常对出现内联注释的代码进行重构来消除需要写注释的情况。

Comments are a great example of something that seems like a Good Thing, but turn out to cause more harm than good. Fortunately, we've figured out how to achieve the same benefits that comments allegedly provide with tests, particularly BDD-style tests

注释是一个非常好的例子证明有些事情表面看起来是“好东西”,但是实际上却会带来比“好处”更多的“坏处” ——得不偿失。幸运的是,我们通过测试,尤其是BDD风格的测试代码,获取了与注释带来的同样的好处。

原创粉丝点击