3

我们都同意重复是邪恶的,应该避免(不要重复自己的原则)。为确保这一点,应使用静态分析代码,如Simian(多语言)或Clone Detective(Visual Studio 插件)

我刚刚阅读了Ayende 关于科比的帖子,他说:

Kobe 的 8.5% 是复制粘贴代码。那就是在灵敏度调高的情况下,如果我们将阈值设置为 3,这是我通常所做的,它会上升到 12.5%。

我认为 3 作为阈值非常低。在我的公司,我们提供质量代码分析即服务,我们的默认重复阈值设置为 20,并且存在大量重复。我无法想象如果我们将其设置为 3,我们的客户甚至都不可能考虑更正。

我理解 Ayende 对 Kobe 的看法:它是一个官方样本,并被宣传为“旨在指导您规划、构建和实施 Web 2.0 应用程序和服务”。所以对质量的期望很高。

但是对于您的项目,您使用什么最小阈值进行复制?

相关问题:您如何狂热地消除代码重复?

4

6 回答 6

4

三是一个很好的经验法则,但这取决于。重构以消除重复通常涉及将代码库和 API 的概念简单性换成更小的代码库,一旦有人理解它就更易于维护。我通常从这个角度来评估事情。

在一种极端情况下,如果修复重复项使代码更具可读性并且对代码的概念复杂性几乎没有增加或根本没有增加,那么任何重复都是不可接受的。这方面的一个例子是,只要将重复的代码巧妙地分解为一个简单的引用透明函数,该函数执行的操作很容易解释和命名。

当需要更复杂、重量级的解决方案(例如元编程、OO 设计模式等)时,我可能会允许 4 或 5 个实例,尤其是在重复的片段很小的情况下。在这些情况下,我觉得解决方案的概念复杂性使治愈比生病更糟糕,直到真的有很多实例。

在最极端的情况下,我正在使用的代码库是一个非常快速发展的原型,我对项目可能发展的方向知之甚少,无法绘制出既合理简单又合理面向未来的抽象线,我只是放弃。在这样的代码库中,我认为只关注权宜之计和完成工作比好的设计更好,即使同一段代码被重复 20 次。通常,创建所有重复的原型部分无论如何都会相对很快被丢弃,一旦你知道原型的哪些部分将被保留,你总是可以重构这些部分。如果没有将被丢弃的部分产生的额外约束,在这个阶段重构通常会更容易。

于 2009-06-16T19:53:32.527 回答
3

我不知道什么是好的“指标”,但我会说我通常努力的目标是

  • 如果您在两个地方有相同的代码,并且
  • 代码是相同的意图(而不仅仅是巧合相同)

然后重构以消除重复。所有的重复都是坏的。我很少让代码在两个地方,而在三个地方,它肯定必须去。

于 2009-04-17T09:10:45.003 回答
1

我个人对此非常狂热。我尝试设计我的项目以避免代码重复。我的目标是让阈值保持在较低的个位数,如果我无法达到,则意味着我的设计还不够好,我需要回到绘图板或重构。

于 2009-04-17T09:07:47.163 回答
1

取决于编程语言。(“克隆侦探”家伙似乎意识到了这一点:“编程语言约束”是他第一次演讲中的框框之一。)

在 Lisp 程序中,任何重复的表达式都很容易被重构——我猜你会称之为阈值 2。一切都是由表达式组成的,并且有宏来翻译表达式,所以很少有任何借口可以复制任何东西甚至一次。(关于我能想到的唯一难以提取的东西就是 LOOP 子句,事实上,很多人正是因为这个原因而主张避免使用 LOOP。)

在许多其他语言中,程序由具有具有语句的方法的类组成,因此很难仅提取一个表达式并在两个不同的文件中使用它。通常,这意味着在提取事物时更改事物的结构。通常还需要类型安全,这可能会受到限制(除非你想一直编写大量反射代码来逃避它,但如果你这样做了,你不应该使用静态语言)。如果我让我当前的静态类型程序完全 DRY,它既不会更短,也不会更容易维护。

我想这样做的结果是我们真正想要的是“易于维护”。有时,在某些语言中,这意味着“只需在此处发表评论,说明您复制的内容和原因”。DRY 是可维护代码的良好指标。如果你经常重复,那不是一个好兆头。但是追逐任何单一的统计数据也往往是不好的——否则,我们会通过简单地优化来解决我们所有的问题。

于 2010-01-20T16:53:47.117 回答
1

我认为我们需要结合

  • 重复的行数
  • 复制的次数
  • 重复项彼此之间有多“接近”,
    例如,如果不同的产品恰好位于同一个源代码控制系统中,那么如果它们采用相同的方法,情况就会大不相同。
  • 自任何包含重复代码的方法被更改以来的时间。

So as to get a good trade-off between cost/benefit of removing the duplicates.

于 2010-03-11T14:17:05.027 回答
0

我们的CloneDR在大型源系统中查找重复代码,包括精确副本和接近未命中,并由语言语法参数化。它支持 Java、C#、COBOL、C++、PHP 和许多其他语言。

它接受许多参数来定义“什么是克隆?”,包括:a)相似度阈值,控制两个代码块必须有多相似才能被声明为克隆(通常 95% 是好的)b)最小克隆的行数大小(3 往往是一个不错的选择) c) 参数的数量(对文本的明显更改;5 往往是一个不错的选择)使用这些设置,它往往会在它处理的几乎所有内容中找到 10-15% 的冗余代码。

于 2009-08-23T05:56:20.010 回答