“评论是一种代码气味”


100

我的一个同事认为,任何使用代码内注释(即,不是javadoc样式方法或类注释)都是一种代码气味。你怎么看?


44
我将对任何回答“否”的答案进行投票。
妮可

2
@Renesis那是神性的味道。
ixtmixilix

107
您的同事进行了全面概括,这自动表示他错了。:)
Alex Feinman

5
@Mongus,我不同意。您的示例中的注释不好不是因为它们是注释,而是因为它们太接近代码,然后代码会更改。他们应该说为什么而不是什么

5
@Alex,这不是一个笼统的概括,因此是错误的(导致他无论如何都没有错)?

Answers:


167

仅当注释描述了代码在做什么时。

如果我想知道某个方法或块中发生了什么,我将阅读代码。无论如何,我希望所有从事给定项目的开发人员至少对开发语言足够熟悉,以阅读所编写的内容并了解其功能。

在某些极端优化的情况下,您可能使用的技术会使某人难以跟踪您的代码在做什么。在这些情况下,注释可以并且应该不仅用于解释为什么要进行这种优化,还可以用于注释代码在做什么。一个好的经验法则是让其他(或多个其他人)熟悉实现语言和项目的人查看您的代码-如果他们既不理解为什么以及如何理解,那么您应该同时评论为什么和如何如何。

但是,代码中尚不清楚的是您为什么要做某事。如果您采取的方法对于其他人来说可能并不明显,那么您应该在注释中说明为什么您做出了自己的决定。我怀疑您可能甚至没有意识到需要注释,直到进行代码审查之类的事情之后,人们才想知道为什么您用X而不是Y-您可以在代码中捕获所有看它的人的答案。在将来。

不过,最重要的是在更改代码时更改注释。如果更改算法,请确保更新注释,以说明为什么使用算法X而不是Y。过时的注释是更大的代码味道。


8
我同意这个答案,但我也看到它被引用为缺乏文档的借口,这是错误的。有时候阅读代码是一件痛苦的事情。你不应该看代码的方法找出该方法做什么。您应该能够从名称中找出来,并从文档中获得更多详细信息。阅读代码时,通常必须在一个类之间切换,并在另一个文件之间切换。这在动态语言中尤其是个问题,在动态语言中,编写可以处理所有这些问题的IDE并非易事。
davidtbernal 2010年

1
无论如何,有时候,如果操作起来很复杂(特别是经过优化或任何其他非平凡的操作),您也必须对其进行评论。如果我不得不花超过5分钟的时间阅读一个代码块以了解它在做什么,那可能会令人沮丧……
Khelben 2010年

3
“仅当注释描述了代码在做什么时。” 或者,如果注释描述了代码的用途;代码已更改,但注释未更改。
Bruce Alderman

1
您如何测试您的评论正确?为什么不写您的评论作为测试?任何将来的维护者都可以将测试用作代码的可验证文档。如果注释与代码的执行有关,那么/ must /必须是可断言的。如果注释与代码的执行无关,那么在只有程序员才能看到的代码中,注释在做什么?
flamingpenguin 2010年

2
@ back2dos,如果您在阅读其他人的代码时经常呕吐,我很高兴我们不共享办公室……

110

此刻听到的消息特别令人不快,我这个周末花了一些时间,看了一个非常有名,非常干净,没有注释的代码,该代码实现了一种研究算法(实际上并未发布)。我对此非常熟悉,坐在我旁边的那个人是发明家,而代码是几年前由其他人编写的。我们几乎不能跟随它。

很显然,您的同事经验不足。


16
我很好奇地看一看很难理解的“名字很好,很干净,没有注释的代码”。我将其归类为此类的任何代码都非常容易遵循。我当然不会说“显然您的同事经验不足”。
Liggy 2010年

8
@Liggy:我会的。这是一种研究算法,而不是业务线应用程序。
保罗·内森

9
我曾经有一段代码,您必须按照“错误”顺序(由过程的“逻辑”和我们的编码标准定义)来填充数据库列对象(第三方)中的字段-按照我们通常会使用,它会崩溃。没有足够的代码阅读量可以告诉您这一点,因此绝对肯定地,必须有一条注释-这不是一种气味,至少在我们控制的代码中(这是底线),这不是一种气味。完全和完全没有评论与不好的评论一样有异味。
Murph 2010年

29
数学,数学,数学。并非所有代码都实现了琐碎的IoC粘合和“价格*数量”。复杂的数学无法神奇地自我解释。
bmargulies 2010年

4
@Liggy,如果没有大量文档,实现复杂数据结构的代码将是完全难以理解的。

75

评论应说明原因,而不是原因。

How通常,使用重构可以更好地处理类型注释。就我个人而言,我通常避免评论赞成重构。

之前:

# convert to cents
a = x * 100

# avg cents per customer 
avg = a / n

# add to list
avgs < avg
t += 1

后:

total_cents = total * 100
average_per_customer = total_cents / customer_count

track_average(average_per_customer)

26
我同意为什么不这样做,并且您的重构在此示例中起作用,但是对于更复杂的代码,没有足够的变量/函数重命名/重构是很有意义的,因此仍然需要注释。
GSto 2010年

3
很好的例子,但是为什么系统使用美分而不是美元呢?这个问题在金融系统中变得很重要,您可能会看到小数货币发挥作用。
rjzii 2010年

3
@Stuart函数的名称应说明其功能。
Alb

3
@GSto,我完全同意。如果代码很复杂,则应将其分解为较小的方法/函数,并使用适当的名称来描述操作。
CaffGeek

1
您假设已经完全控制了代码库。
LennyProgrammers 2011年

32

我宣布你的同事是异端!我的异端燃烧靴子在哪里?

强迫性注释是不好的,而且维护起来很头疼,注释不能替代名称明确的方法,类,变量等。但是有时说明为什么要这样做,对于必须维护代码的可怜白痴来说可能是非常有价值的在六个月之内-尤其是当那个可怜的白痴成为你的时候。

我正在处理的代码中的一些实际注释:


    // If this happens, somebody's been screwing around with the database definitions and
    // has removed the restriction that a given alarm may have only one entry in the 
    // notifications table.  Bad maintenance programmer!  Bad!  No biscuit!



    // If an alert is active on our side but inactive on theirs, that might mean
    // they closed the alert.  (Or that we just haven't told them about it yet.)  The
    // logic comes later; for now, we'll just compile it in a list.



    // If we know for a fact that an alarm isn't getting through, we're going to whine pretty
    // aggressively about it until it gets fixed.


7
+1为好评论。没有大量的代码可以说“如果发生这种情况,那就是有人在搞乱数据库定义”。
DistantEcho

9
@Niphra,好吧,我们可以抛出一个SomebodyScrewedAroundWithDatabaseException...

@Thorbjørn+1,如果代码知道出了什么问题,那就报告一下。客户支持技术人员可能会重新加载数据库,并避免进行服务呼叫。
Tim Williscroft 2010年

@Tim,正如客户可能看到的那样,更中性的命名可能是合适的。

3
当然,请记住:永远不要使用愚蠢的名字。客户将始终看到它们。
Tim Williscroft 2010年

29

理想情况下,代码应该被很好地编码,以使其具有自动解释性。在现实世界中,我们知道有时也需要注释非常高质量的代码。

您绝对应该避免的是“注释代码冗余”(注释不会在代码中添加任何内容):

i++; // Increment i by 1

然后,如果有一个好的(并且保持/保持一致的)代码设计和文档,那么注释就没什么用处了。

但在某些情况下,注释可以帮助提高代码的可读性:

while( foo )
{
     if( dummy )
     {
     }
     else // !dummy
     {
     }
} // end while( foo )

别忘了您还必须维护和保持评论同步...过时或错误的评论会带来极大的痛苦!而且,通常来说,注释过多可能是不良编程的征兆。


2
好的命名约定和结构良好的代码将帮助您减少注释的需要。不要忘记,您添加的每一行注释都是要维护的新行!!
加布里埃尔·蒙贡

81
我讨厌别人在您的问题中使用第二个例子。} //end while只是意味着while循环的开始距离很远,您甚至看不到它,也没有暗示您正在查看的代码处于循环中。对于代码的结构注释,应该优先考虑使用重重构。
卡森·迈尔斯

4
@Carson:虽然将块缩短是一个众所周知的规则,但这并不意味着我们总是可以应用它。
Wizard79 2010年

4
@Carson:我从事的项目之一没有足够的代码审查,这导致了一系列JSP的循环复杂性“ OMFG只是杀死了你自己”。重构血腥的事物代表着需要在其他地方花费的工作日。这些} // end while评论可以挽救生命。
BlairHippo

11
@BlairHippo:“ [A]代码气味是程序源代码中的任何症状,可能表明存在更深层的问题”。当然,此评论可以挽救生命,但是OMGWTF循环是前面提到的“更深层次的问题”,而且挽救生命的必要性是一个明确的指标;)
back2dos

26

将方法或过程分类定义为“代码气味”是“狂热气味”。该术语正在成为新的“被认为有害”。

请记住,所有这些事情都应该作为指南。

许多其他答案对于何时发表评论提供了很好的建议。

我个人很少使用评论。说明非显而易见的过程的目的,并将偶尔的死亡威胁留给可能正在考虑自己进行更改并需要数周调整的任何人。

重构所有内容,直到幼儿园可以理解为止,这可能无法有效地利用您的时间,并且可能无法获得更简洁的版本。

注释不会影响运行时间,因此唯一需要考虑的负面问题就是维护。


8
我认为“反模式”是新的“考虑有害”。代码气味只是需要仔细检查以进行可能的清理的东西。
Jeffrey Hantin

1
我不同意反模式也符合条件。当设计足够复杂以至于显然是一个故意的选择时,它们都以反图案代替气味的方式使用。无论哪种情况,我都不同意在这些事情上存在绝对正确的观念。
条例草案

4
+1表示“重构所有内容,直到幼儿园老师可以理解,这可能不会有效地利用您的时间,并且可能不会表现得更简洁。”
Earlz 2011年

23

在某些情况下,良好的命名,重构等功能都无法替代注释。看看这个真实的例子(语言是Groovy):

  response.contentType="text/html"
  render '{"success":true}'

看起来很奇怪,不是吗?可能是复制粘贴错误?哭了一个错误修正?

现在与注释相同:

  // DO NOT TOUCH THE FOLLOWING TWO LINES; the ExtJS UploadForm requires it exactly like that!!!
  response.contentType="text/html"  // must be text/html so the browser renders the response within the invisible iframe, where ExtJS can access it
  render '{"success":true}'         // ExtJS expects that, otherwise it will call the failure handler instead of the succss handler

函数prime_extjs_uploadform(){response.contentType ='text / html'; 渲染'{“ success”:true}'; } prime_extjs_uploadform();
DrPizza 2012年

23

这里的主要问题是术语“代码气味”的含义。

许多人(我认为包括您在内)都了解代码气味是接近错误的东西,或者至少是需要修复的东西。也许您认为它是“反模式”的同义词。

这不是这个词的意思!

代码气味隐喻源自Wards Wiki,他们强调:

请注意,CodeSmell暗示可能出了问题,而不是确定性。完美的习惯用法可能被认为是CodeSmell,因为它经常被滥用,或者因为在大多数情况下有一个更简单的替代方法可以起作用。调用CodeSmell并不是攻击。这只是一个迹象表明必须仔细观察。

因此,注释是代码气味的意思是什么:它意味着当您看到注释时,您应该停下来思考:“嗯,我感觉到有一些可以改进的提示”。也许您可以重命名变量,执行“提取方法”重构-也许注释实际上是最好的解决方案。

这就是注释成为代码气味的含义。

编辑:我只是绊倒在这两篇文章,这比我更好地解释了:


2
我很惊讶,这个答案花了两个月的时间。它表明了对该术语的误解有多普遍。
Paul Butcher

一般情况的断言仍然是错误的。您不会说:“我看到的是注释代码。这是一个不好的信号。”
Stuart P. Bentley

1
@Stuart:您正在查看两个代码块,每个代码块都有适当的注释级别。(此问题不是有关注释的适当数量,而是有关根据注释数目判断代码的方式。)一个没有注释,另一个没有注释。您更看哪一个?-注释表明代码复杂而微妙,因此更有可能出现问题。
David Schwartz

这是正确的答案。
vidstige'2

21

我认为规则很简单:想象一个完全陌生的人看到您的代码。您可能会在5年后对自己的代码陌生。尽量减少为了解此陌生人的代码而付出的精力。


8
+1对于尚未在单个项目上工作过足够长的时间来体验这一点的开发人员,请相信我会成功的。每当我以这种艰难的方式学习并且不得不重新学习自己的代码时,我就不会再犯两次相同的错误并在继续进行其他操作之前先对其进行注释。
妮可

不,您应该想象一个精神病患者知道您的住所:他们会乐于维护您的代码吗?
理查德

4
当我看到不可读的代码时,我经常会变得精神病。
LennyProgrammers

3
5年?大约5分钟。;)
Alex Feinman

11

拥有正确评论的一个好主意是从编写评论开始。

// This function will do something with the parameters, 
// the parameters should be good according to some rules.
myFunction(parameters)
{
    // It will do some things to get started.

    // It will do more with the stuff.

    // It will end doing things with the stuff.
}

这使您可以轻松提取方法,甚至摆脱注释,
只需让代码告诉这些事情即可!看看如何以非常好的方式重写(剪切/粘贴):

// This function will do something with the parameters, 
// the parameters should be good according to some rules.
myfunction(parameters)
{
  var someThing = initializedWithSomething;

  doSomethingWith(someThing);

  doMoreWith(someThing);

  endDoingThingsWith(someThing);

  return someThing;
}

// This function will do some things to get started,
// the parameters should be good according to some rules.
doSomethingWith(parameters)
{
  parameters.manipulateInSomeWay();
  ... etc ...
}

... etc ...

对于无法分离的事物,请不要提取方法并在注释下键入代码。

我认为这是将注释保持在最低限度的一种有用方法,对每一行进行注释真的没有用...仅记录一行有关魔术值初始化或有意义的地方。

如果参数使用过多,则它们应该是您的类中的私有成员。


1
这就是我的工作。如果您认为需要评论,我可以建议您尝试一下。
bzlm

10

我认为答案是通常的“取决于”之一。仅仅为了注释代码而注释代码是一种气味。注释代码是因为您使用的模糊算法的速度快一个数量级,因此可以节省维护程序员(通常是我在编写代码后的6个月内),以节省半天的时间来确定代码在做什么。


10
// Dear me in the future. Please, resolve this problem.

要么

// You think this code was written by somebody else. 
// No, it wasn't. You ([some name]) did it.

啊,衷心请未来的自己。
Anthony Pegram

8

代码注释绝对不是“代码气味”。这种信念通常来自以下事实:评论可能会陈旧(过时)并且难以维护。但是,拥有良好的注释可以解释为什么代码以某种方式做某件事对于维护很重要(通常很重要)。

好的注释可以使您更容易理解代码在做什么,更重要的是,为什么要以特定的方式进行代码。注释应供程序员阅读,并且应清晰准确。难以理解或不正确的评论比根本没有评论要好得多。

在代码中添加清晰准确的注释意味着您不必依靠内存来理解代码部分的“内容”和“原因”。这一点在以后查看该代码时非常重要,否则其他人必须查看您的代码。因为注释已成为代码文本内容的一部分,所以除了清晰书写外,它们还应遵循良好的书写原则。

要写一个好的评论,您应该尽力记录代码的目的(为什么而不是如何),并尽可能清楚地说明代码背后的原因和逻辑。理想情况下,注释应在编写代码的同时编写。如果您等待,您可能不会回去添加它们。

Sams在24小时内自学Visual C#2010,第348-349页。


1
注释可能会过时,但是对于未经编译器或单元测试验证的所有内容,例如类,函数和变量名的含义,都是如此。
LennyProgrammers 2010年

@ Lenny222:是的,评论可能会过时...这通常表示懒惰的程序员。如果注释描述了为什么进行决策,代码为何使用特定算法进行计算或描述了代码如何运行,那么除了有人更改了实现并没有相应更新注释之外,没有其他理由使注释变得陈旧。 -等同于懒惰。
Scott Dorman 2010年

2
我同意。我的意思是,它有过时的风险,是的。但是,当我有一个函数doBar()并在3年后不再“做bar”,而是“除了星期三之外就做bar和foo”时,函数的含义也会过时。和变量名。但是,我希望没有人因为没有给函数和变量赋予有意义的名称的原因。
LennyProgrammers 2010年

6

如果已以某种特定方式编写了代码,以避免出现库(第三方库或编译器随附的库)中存在的问题,则可以对其进行注释。
例如,注释需要在将来版本中更改的代码,或者在使用库的新版本时,或者从PHP4传递到PHP5时,也可以使用注释。


6

即使是写得最好的书,也很可能会有引言和章节标题。记录良好的代码中的注释对于描述高级概念以及解释代码的组织方式仍然很有用。


这种注释提供了很好的视觉提示,因此您不必阅读每一行就可以找到要查找的部分的开头。就像我祖父曾经说过的:“一切都要适度”。
Blrfl 2011年

4

值得一提的是反模式:

我的印象是,有时会经常使用FLOSS许可证的示例来代替文件文档。GPL / BSDL是一个很好的填充文本,此后您几乎看不到任何其他注释块。


4

我不同意写注释来解释代码的想法不好。这完全忽略了代码存在错误的事实。这可能是清楚的代码是什么不评论。不太清楚代码该做什么。如果没有评论,您如何知道结果是否错误或使用不正确?

注释应说明代码的意图,以便在出现错误时阅读注释+代码的人有机会找到它。

通常,编写代码之前,我通常会先编写内联注释。这样一来,我就可以清楚地知道我要编写的代码,并减少了在算法中不会真正知道自己在做什么的迷路。


1
单元测试有助于确定结果是否错误。如果您阅读了一些代码,并认为实际上是X,那么实际上是X,那么代码可能没有以足够可读的方式编写。我不确定您对错误使用结果的意思。注释不能防止您以奇怪的方式使用代码。
亚当李尔

“如果您读了一些代码,并认为实际上是X,那么实际上是Y”,这不是我所说的。我说的是理解什么代码确实做的,但是不知道它应该做的事。假设您怀疑一个错误。您如何知道一次性代码错误不在使用代码中,也不在此代码中?注释解释了代码的意图,这对跟踪错误有很大帮助。
Danny Tuppeny

另一方面,注释可能只告诉您在编写注释时代码应该做什么代码本身可能会告诉您现在应该做什么注释不编译。您无法测试评论。它们可能正确也可能不正确。
安东尼·佩格拉姆

3

因为有人认为一种方法中包含700行是可以闻到的,所以添加了注释。

之所以有这样的评论,是因为您知道如果不发表评论,就会有人犯同样的错误,但又是一种气味。

插入注释是因为某些代码分析工具要求它也是一种气味。

不会的人曾经加入了注释,或写甚至其他开发者一点帮助也有异味。令我惊讶的是,有多少人没有写下来,但随后转身承认他们不记得他们三个月前的所作所为。我不喜欢写文档,但我想一次又一次地告诉人们同一件事。


3

我将自己回答一个问题。您可以在下面未注释的代码中找到该错误吗?

tl; dr:下一个维护您代码的人可能不像您那样敬虔。

 [org 0x7c00]

 main:
  mov ah, 0x0e
  mov bx, string
  call strreverse
  call print

 stop:
  jmp $

 strreverse:
  pusha
  mov dx, bx
  mov cx, 0

 strreverse_push:
  mov al, [bx]
  cmp al, 0
  je strreverse_pop
  push ax
  add bx, 1
  add cx, 1
  jmp strreverse_push

 strreverse_pop:
  mov bx, dx

 strreverse_pop_loop:
  cmp cx, 0
  je strreverse_end
  pop ax
  mov [bx], al
  sub cx, 1
  add bx, 1
  jmp strreverse_pop_loop

 strreverse_end:
  popa
  ret

 print:
  pusha

 print_loop:
  mov al, [bx]
  cmp al, 1
  je print_end
  int 0x10
  add bx, 1
  jmp print_loop

 print_end:
  popa
  ret
 string:
  db 'Boot up', 0

 times 510 -( $ - $$ ) db 0
 dw 0xaa55

但是,在当今时代,您不是在使用高级语言吗?
伊恩

2
@Ian:该程序是IBM-PC引导程序。您不能用汇编以外的任何方式编写它,因为您需要完全控制程序在RAM中的位置,最后一个短字符出现的位置以及某些硬件中断。认真地,给自己买一份NASM。组装它,将其写入软盘或USB记忆棒的启动扇区,然后启动它。尽管您可能会发现由于该错误,它无法按预期工作。现在查找错误...无论如何,我敢肯定,从现在开始的20年后,人们会问同样的事情,即未注释的Java。
蚂蚁

可以肯定的是,代码可以用C或C ++编写,而二进制文件则由C对象代码和一些外部工具汇编而成。
凯文·克莱恩

不幸的是没有。在CodeProject上查看此页面:codeproject.com/KB/tips/boot-loader.aspx- “高级语言没有必要的说明”。不仅如此,在引导装载程序中您还可以使用512个字节。有时,您只需要直接使用硬件即可。
蚂蚁

1
在编写汇编代码时,我会做其他所有人都会做的事情-在每一行中注释其正在做的事情。由于代码使用C样式的0终止字符串,因此该行将带有注释“检查字母是否为0”。有了适当的注释后,很容易看到代码使用1执行cmp,这意味着它要么陷入无限循环,要么打印垃圾,直到它在RAM中达到随机1。我可能还添加了有关字符串以0终止的事实的注释,这在代码中并不明显。是否存在用于汇编代码的自动化单元测试之类的东西?
蚂蚁

2

您必须在代码和注释之间保持平衡...通常,我会尝试添加一些可恢复代码块的注释。不是因为我无法理解代码(嗯,也是),而是因为我可以更快地阅读自己的代码,并在发生重大事件的地方找到特定的部分。

无论如何,我个人的标准是“有疑问时发表评论”。我更喜欢有一条冗余线,而不是一条我不会理解的完全神秘的线。一段时间后,我总是可以删除代码审查中的注释(我通常这样做)

另外,注释添加“ caveats”非常有用,例如“注意!如果输入的格式不是ASCII,则必须更改此代码!”


您能解释一下“恢复一段代码的注释”的意思吗?
Mark C 2010年

2

阅读此书时,我想起了几十年前我第一次阅读的内容(从更长的列表中保留下来,并通过影印件保存):

真正的程序员不写评论-如果很难写,应该很难阅读

闻起来有点老。


2

我认为代码注释起步很糟糕。我不知道这些日子,但是当我在学校第一次学习编程时,我得到了“编写一个将数字以十到十的数字打印在单独的行中的程序。请确保对代码进行注释”的性质。如果您不添加注释,则会被打下标记,因为注释您的代码是一件好事。

但是,对于这样一个微不足道的过程,有什么要说的呢?所以你最终写经典

i++; // add one to the "i" counter.

只是为了获得一个不错的成绩,并且,如果您一点都不喜欢,就会立即对代码注释发表意见。

代码注释不是一件好事。这是有时必要的事情,而在最上面的答案中的托马斯·欧文斯(Thomas Owens)很好地解释了必要的情况。但是,这些情况很少出现在家庭作业类型的作业中。

在许多方面,当不能在编程语言的有效部分中明确说出需要说的内容时,添加注释应被视为最后的选择。尽管对象命名可能会过时,但是各种人为和计算机缺乏反馈的机制使忘记维护注释变得容易,因此注释比活动代码更快地过时。因此,在可能的情况下,始终应该选择更改代码使其更清晰,而不是使用注释注释不清晰的代码。


+1指出不良的评论习惯始于早期的编程课程。结论为-1只是不得已而为之。
AShelly

1

当然注释是代码的味道...

每个程序员都知道,由于工作量,调试或遇到的疯狂行为,我们最终都会变得疯狂

“做这个!” 您的项目经理说。

您回答:“无法完成。”

他们说:“那么我们会找其他人去做。”

您说:“好的,也许可以做到。”

然后花接下来的X天数..周..月..试图找出答案。在整个过程中,您将尝试失败,并且尝试失败。我们都这样做。真正的答案是有两种类型的程序员,一种是注释的,另一种是不注释的。

1)这样做的目的是通过编写文档以备将来参考,注释掉不起作用的失败例程(发现有用的例程后气味并没有删除它们),从而使自己的工作变得更容易,或者通过注释分解代码格式化到希望使它有点更容易阅读和理解。说真的,我不能怪他们。但最后,它们会折断,然后您会得到以下信息: // dammit this code sucks! swear! curse! i hate it! i am going to write something here to vent my anger!!!!

2)那些没有装扮成超级英雄或住在山洞里的人。他们只是鲁re地无视他人,而对代码或以后可能具有的含义则不太在意。

现在不要误会我..自记录变量和函数可以完全避免这种情况.. 相信我,您永远无法进行足够的代码清理。但简单的事实是,只要保留备份,就可以始终删除注释。


1
响应1.在注释例程中,真正的气味不是在您确定它们可能是死胡同并想尝试其他方法时不会立即删除它们-这是因为,如果您决定重新访问它们,它们应该在版本控制中可用。
Sharpie

1

我认为在代码中不使用一些注释是一种代码味道。尽管我同意代码应该尽可能地自我记录,但是您遇到了某个问题,无论代码编写得如何好,您都会看到毫无意义的代码。我在业务应用程序中看到了一些代码,其中的注释几乎是必需的,因为:

  1. 您需要根据情况做一些事情,并且没有很好的逻辑。
  2. 更改法律后,您可能会在一两年内更改代码,而您想迅速找到它。
  3. 过去有人编辑过代码,因为他们不了解代码在做什么。

同样,公司风格指南可能会告诉您以某种方式做某件事-如果他们说您应该有注释,概述函数中正在执行的代码块,然后包含这些注释。


1

注释和代码之间存在很大的根本区别:注释是人们与他人交流思想的一种方式,而代码主要是用于计算机的。“代码”中有许多方面也只适用于人类,例如命名和缩进。但是评论是由人类严格为人类编写的。

因此,撰写评论与书面交流一样困难!作者应明确了解谁是受众,以及他们将需要哪种文本。您怎么知道谁会在十年,二十年后阅读您的评论?如果此人来自完全不同的文化怎么办?等等,希望大家都理解。

即使在我所居住的同质小文化中,也很难与他人交流思想。人为交流通常会失败,除非是由于意外。


0

我必须同意你的同事。我总是说,如果我的评论我的代码,这意味着我担心,将无法弄清楚自己的代码在未来。这是一个坏兆头。

我向代码中添加注释的唯一其他原因是要调用似乎没有意义的内容。

这些评论通常采用以下形式:

//xxx what the heck is this doing??

要么

// removed in version 2.0, but back for 2.1, now I'm taking out again

1
或者,注释也可以反映以下事实:代码正在处理一种复杂的算法,在该算法中,代码固有地变得不明显,或者由于由于您无法控制的因素(例如,与外部服务进行交互)而使代码做得有些奇怪。
Murph 2010年

非常真实 有很好的代码可能并不明显的原因。尽管在大多数情况下,令人困惑的代码是令人困惑的,因为它们是以混淆的方式编写的。

似乎您还没有为只有32k的嵌入式处理器编写代码,而这确实使您望而却步。评论是挽救生命的。
quick_now 2011年

0

代码注释在适当的地方提供了函数参数和返回值的单位,结构字段,甚至局部变量,都非常方便。记住火星轨道器!


将单元构建为变量名称要好得多,因此可怜的程序员不必记住它们。而不是'double length // in meter',而不是'double length_m'。最棒的是使用一种更强大的语言,因此您可以简单地说:力f; 扭矩t = l * f; 打印(t.in(Torque.newtonMeter));
凯文·克莱恩

0

这是我的经验法则:

  • 编写代码,并将代码的简短摘要存储在单独的文档中。
  • 将代码放置几天,以进行其他操作。
  • 返回代码。如果您无法立即了解它的功能,请将摘要添加到源文件中。


0

不,注释不是代码的味道,它们只是可以滥用的工具。

好的评论示例:

//我认为这是厘米。需要进一步调查!

//这是做X的聪明方法

//此处的列表保证为非空


第三个是IMO的不好评论。为什么不Assert(list.IsEmpty)呢?
CodesInChaos 2012年

@CodeInChaos IMO Assert(!list.isEmpty())与第三条注释中的约定并不完全相同,只是行为(例如,如果参数为空,则抛出IllegalArgumentException),该行为必须像任何其他程序逻辑一样进行单元测试。注意注释的细微差别,该注释指出何时可以使用该方法,但是如果不满足前提条件,则不指定任何行为。比评论更好的是执行编译时合同。但是,这超出了我的回答范围;)
Andres F.

您不应执行Asserts,因为它们描述了永远都不会发生的事情,即使公共API接收到无效的参数也是如此。
CodesInChaos 2012年

@CodeInChaos我撤回我的意见。这是Sunacle关于断言的说法。看来你是对的。好吧,你每天都学到一些东西!
Andres F.
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.