如何在开发过程中检测代码重复?

我们有一个相当大的代码库,C ++的400K LOC,代码重复是一个问题。 有什么工具可以有效地检测重复的代码块吗?

理想情况下,开发人员可以在开发过程中使用这些function,而不是偶尔运行以查看问题所在。 如果我们能够在CruiseControl中整合这样一个工具,并在每次登记后给出一个报告,那也不错。

我前段时间看了一下Duploc ,它显示了一个很好的graphics,但是需要一个小型的环境来使用它,这使得它自动运行起来相当困难。

免费工具会很好,但如果有一些好的商业工具,我也会感兴趣。

Simian在C ++项目中检测到重复的代码。

更新:也适用于Java,C#,C,COBOL,Ruby,JSP,ASP,HTML,XML,Visual Basic,Groovy源代码甚至纯文本文件

我已经使用了PMD的复制和粘贴检测器,并通过使用下面的包装脚本(确保在类path中具有pmd jar)将其集成到CruiseControl中。

我们的支票每晚运行。 如果您希望限制输出以仅列出当前更改集合中的文件,则可能需要一些自定义编程(想法:全部检查并仅列出涉及其中一个已更改文件的重复项目。必须检查所有文件,因为更改可能会使用来自未更改文件的一些代码)。 应该可以通过使用XML输出和parsing结果来实现。 完成后不要忘记发布该脚本;)

对于初学者来说,“文本”输出应该没问题,但是您希望以用户友好的方式显示结果,为此我使用Perl脚本从CPD的“xml”输出生成HTML文件。 这些可以通过张贴到巡航的报告jsp所在的tomcat来访问。 开发人员可以从那里查看他们,看到他们的肮脏的黑客的结果:)

它运行得非常快,在150个KLoc代码上不到2秒钟(空行和注释不在这个数字中)。

duplicatecheck.xml

<project name="duplicatecheck" default="cpd"> <property name="files.dir" value="dir containing your sources"/> <property name="output.dir" value="dir containing results for publishing"/> <target name="cpd"> <taskdef name="cpd" classname="net.sourceforge.pmd.cpd.CPDTask"/> <cpd minimumTokenCount="100" language="cpp" outputFile="${output.dir}/duplicates.txt" ignoreLiterals="false" ignoreIdentifiers="false" format="text"> <fileset dir="${files.dir}/"> <include name="**/*.h"/> <include name="**/*.cpp"/> <!-- exclude third-party stuff --> <exclude name="boost/"/> <exclude name="cppunit/"/> </fileset> </cpd> </target> 

duplo似乎是Duploc中使用的algorithm的C实现。 编译和安装很简单,虽然这些选项是有限的,但似乎或多或less都是开箱即用的。

看看PMD项目 。

我从来没有用过,但一直都想。

对于我自己的将来的参考,这些Debian软件包似乎做这样的事情

  • 相似度testing器 (也称为软件和文本相似度testing器SIM )

  • simhash

我可以发誓我已经安装了一些可能更加相关的软件包,但目前我找不到它们。 (这就是为什么我这次在这里列出我的发现:让自己有机会再次find他们!)

PS它似乎应该有一个与所有工具相关的寻找[近]重复的debtags标签。 (但是会叫什么?)

那么,你可以每天晚上在你的源代码库上运行一个克隆检测器。

许多克隆检测器通过比较源代码行工作,只能find确切的重复代码。

上面的CCFinder通过比较语言标记来工作,所以它对空白变化不敏感。 如果只有单个标记更改(例如,将克隆中的variablesX更改为Y),它可以检测到原始代码变体的克隆。

理想情况下,你想要的是上面的内容,但是能够find允许变化相对任意的克隆,例如,用expression式replacevariables,用块表示语句等等。

我们的CloneDR克隆检测器为Java,C#,C ++,COBOL,VB.net,VB6,Fortran和其他各种语言提供了这种function。 可以在http://www.semdesigns.com/Products/Clone/index.html上看到;

除了能够处理多种语言,CloneDR引擎还能够处理各种input编码风格,包括ASCII,ISO-8859-1,UTF8,UTF16,EBCDIC,许多Microsoft编码和(日文)Shift- JIS。

该站点有几个克隆检测运行示例报告,其中包括一个用于C ++的报告。

编辑2014年2月:现在处理所有的C + + 14。

CCFinderX是一个免费的(内部使用)克隆代码检测器,支持多种编程语言(Java,C,C ++,COBOL,VB,C#)。

查找“相同”的代码片段相对容易,现有的工具已经做到了这一点(见其他答案)。

有时这是一件好事,有时候不是; 如果在一个太高的“水平”上完成,它可能会阻碍开发时间; 即试图重构这么多的代码,你放松你的目标(可能会破坏你的里程碑和时间表)。

更难的是find多个function/方法做同样的事情,但有不同(但相似)的input和/或algorithm没有适当的文件。

如果你需要两种或不同的方法来做同样的事情,程序员试着去修复一个实例,但忘记(或不知道它们存在)来修复其他实例,那么你将会增加软件的风险。

Same( http://sourceforge.net/projects/same/ )是非常简单的,但它在文本行而不是令牌,这是有用的,如果你使用的语言不支持的一个发烧友克隆发现者。

ConQAT是支持C ++代码分析的一个很好的工具。 可以find忽略空格的重复项。 有extreamly方便的GUI和控制台界面。 由于它的灵活性,它不是一个容易设置。 我发现这个博客文章非常有用的设置c + +项目 。

您可以使用我们的数字源表工具来检测代码重复。 它是一个命令行工具(非常类似于编译器),所以你可以很容易地将它集成到持续集成工具,比如你提到的CruiseControl或者Jenkins 。

还有Simian ,它支持Java,C#,C ++,C,Objective-C,JavaScript …

它得到了哈德森 (如CPD)的支持。

除非你是一个开源项目,否则你必须为Simian 支付费用

TeamCity为.NET和Java提供了强大的代码复制引擎,可以毫不费力地作为构build系统的一部分运行。