你容忍多少重复的代码?

Syl*_*ain 49 refactoring coding-style dry code-duplication

在最近的一次代码审查中,我在一个类中发现了几行重复​​逻辑(少于15行).当我建议作者重构代码时,他认为代码更容易理解.在再次阅读代码后,我不得不同意提取重复的逻辑会稍微损害可读性.

我知道DRY是指南,而不是绝对的规则.但总的来说,你是否愿意以DRY的名义伤害可读性?

Nic*_*kis 58

重构:改进现有规范的设计

三规则

你第一次做某事,你就是这样做的.第二次你做
类似的事情,你在复制时畏缩,但
无论如何你都做了重复的事情.你第三次做类似的事情,你重构.

三次罢工,你重构.


工作中的编码员

Seibel:所以对于这些XII调用中的每一个,你都在编写一个实现.
你有没有发现你在积累大量非常相似的代码?

Zawinski:哦,是的,当然.通常在第二次或第三次你剪切并粘贴
那段代码时,好吧,是时候停止剪切和粘贴并将其放入子程序中.

  • +1 - 此外,三规则不仅仅是一种启发式方法,而是一种已经被研究过的东西.它适用于小型冗余以及整个框架(产品线驱动开发).你的收益实际上在2.5左右,以便找回重复使用和复制/黑客的成本. (6认同)
  • 我认为这应该是"两个规则".请参阅我对此OP问题的回答. (5认同)
  • 第一次不是重复的。第二次是。第三次是第二次重复,这是我们应该重构的提示。这里的关键是,当你只使用一次时,你不会*总是*想要尝试打破某些东西以使其可重用。 (2认同)

Vin*_*vic 41

我绝不容忍.由于时间限制或诸如此类的原因,我最终可能会遇到一些问题.但我仍然没有找到重复代码真正需要的案例.

说它会损害可读性只表明你擅长挑选名字:-)

  • 关于挑选好名字的评论+1.我很难看到如何调用具有合理名称的方法比十几行代码更不易读...特别是因为当你看到第二次调用相同的方法时,在决定"是的,和以前一样的东西"之前你不必阅读一堆行. (9认同)
  • 我也不容忍.重复的代码将来一直困扰着你. (6认同)
  • 也许找到一个名字很难的原因是因为它没有映射到一个漂亮的,可打包的概念.也许重复的代码不是一个明智的独立功能单元.如果你必须在阅读之前跟踪代码,它会损害可读性,而你必须阅读它,因为你将代码拆分成没有意义的块.正如sleske所说,重构基于什么是有意义的,而不是*只是*什么是重复的. (3认同)
  • 我不想容忍任何,但现实世界中我可以在项目上花费多少时间的预算限制可以决定我可以进行多少重构。另一种方法是免费重构代码。 (2认同)

Ree*_*sey 32

就个人而言,我更喜欢保持代码可以理解,首先是.

DRY是关于简化代码维护的.在许多情况下,使代码不易理解以删除重复的代码会比使用重复的代码行更容易损害可维护性.

话虽如此,我确实同意DRY是一个很好的目标,在可行的情况下.

  • 我同意.DRY是一种用于实现可维护性和可读性的工具.DRY本身不是目标. (6认同)
  • @Laykes:"不要重复自己." (6认同)
  • @Vinko:我见过的唯一一次是代码总行非常短(总共2-3行),并且你必须在重复行之间运行逻辑.这可以使用函数式重构来创建DRY,但是它往往会增加维护成本,因为它几乎总是强制引入方法指针/ lambda/delegate/etc(取决于语言). (2认同)

Ira*_*ter 12

如果相关代码具有明确的业务或技术支持目的P,您通常应该重构它.否则,您将遇到克隆代码的经典问题:最终您将发现需要修改支持P的代码,并且您将找不到实现它的所有克隆.

有些人建议3个或更多副本是重构的门槛.我相信如果你有两个,你应该这样做; 无论你有两个或三个或更多,在大系统中找到其他克隆[甚至知道它们可能存在]都很难.

现在,在没有任何工具来查找克隆的情况下提供此答案.如果你可以可靠地找到克隆,那么重构的原因(避免维护错误)就不那么具有持久性了(具有命名抽象的效用仍然是真实的).你真正想要的是一种查找和跟踪克隆的方法; 抽象它们是确保你"找到"它们的一种方法(通过使发现变得微不足道).

可以可靠地查找克隆的工具至少可以防止您进行无法更新克隆的维护错误.一个这样的工具(我是作者)是CloneDR.CloneDR使用目标语言结构作为指导查找克隆,因此无论空格布局,注释中的更改,重命名的变量等如何都可以找到克隆(它适用于多种语言,包括C,C++,Java,C#,COBOL和PHP) ).CloneDR将在大型系统中找到克隆,而不会给出任何指导.显示了检测到的克隆以及反清除器,它实际上是您可能编写的抽象.它的版本(对于COBOL)现在与Eclipse集成,并在您在缓冲区中的克隆内部以及其他克隆的位置进行编辑时向您显示,以便您在那里时可以检查/修改其他克隆.(你可能做的一件事就是重构它们:).

我曾经认为克隆是完全错误的,但是人们这样做是因为他们不知道克隆与原始克隆会有什么不同,所以最终的抽象在克隆行为发生时并不明确.现在我相信克隆是好的,如果你可以跟踪克隆,并在抽象变得清晰后尝试重构.

  • 我必须同意你的看法.如果重复的代码重复执行相同的操作,那么无论它正在做什么都有一个名称,并且值得考虑因素,以便可以根据该名称的语义来看待它,而不是语法的细节.这简化了维护,实际上使代码*更容易*阅读. (3认同)
  • +1:这是许多敏捷方法推荐的方法:首先实现新功能,复制和粘贴,因为你觉得有必要.然后,当它完成后,你重构.这个想法是,在实现完成后,您将更好地了解抽象是否合适. (2认同)

Uns*_*ced 8

一旦你重复任何事情,你就会创建多个地方进行编辑,如果你发现你犯了错误,需要扩展它,编辑,删除或者你可能遇到的其他几十个原因强迫改变.

在大多数语言中,将块提取到适当命名的方法很少会损害您的可读性.

这是你的代码,符合你的标准,但我的基本答案是你的"多少钱?" 是 ...