在开发过程中如何检测代码重复?[关闭]


78

我们有一个相当大的代码库,C ++的LOC为400K,并且代码重复是一个问题。是否有任何工具可以有效地检测重复的代码块?

理想情况下,开发人员可以在开发过程中使用它,而不仅仅是偶尔运行以查看问题所在。如果我们可以将这样的工具与CruiseControl集成在一起,在每次签入后提供报告,那也很好。

我前段时间看过Duploc,它显示了一个漂亮的图形,但是需要一个Smalltalk环境才能使用它,这使得自动运行非常困难。

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


3
每当有人使用粘贴按钮时:-}
Ira Baxter,2009年

Answers:


35

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

更新:还可与Java,C#,C,COBOL,Ruby,JSP,ASP,HTML,XML,Visual Basic,Groovy源代码甚至纯文本文件一起使用


可以无缝地检查.mm文件,又称为ObjectiveC ++
rraallvv 2013年

1
@rraallvv Simian可以进行纯文本检查,因此可以检测任何语言的代码重复。
Catharz

2
请注意,它不是免费用于商业用途。
Zitrax

如果仅使用Linux上目录中的默认设置运行它,则它似乎无法递归工作。
ZeroPhase

20

我使用了PMD的“复制并粘贴检测器”,并通过使用以下包装器脚本将其集成到CruiseControl中(请确保在类路径中有pmd jar)。

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

对于初学者,“文本”输出应该可以,但是您将希望以一种用户友好的方式显示结果,为此,我使用perl脚本从CPD的“ xml”输出中生成HTML文件。通过将它们发布到Cruise的报告jsp所在的tomcat中,可以访问这些文件。开发人员可以从那里查看它们,并查看其恶意入侵的结果:)

它运行非常快,在150 KLoc代码上不到2秒(空行和注释未计入该数字)。

plicatecheck.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>


确保使用sourgeforge页面上的最新版本!他们的文档页面建议使用2011年的版本,但仍在积极开发中。在我的案例中,5.5版比其链接到其首页的4.2版要好得多。
2016年

他们的文档中也不再提及C ++支持。
ZeroPhase


6

duplo似乎是Duploc中使用的算法的C实现。它的编译和安装很简单,并且在选项受限制的情况下,它或多或少地是开箱即用的。


我只是在一个相当老旧的,几乎有很多重复的代码文件上进行了尝试,然后将其与最近的几乎没有重复的代码文件进行了比较。旧文件被评为完美。新文件被评为不良。
塞巴斯蒂安·马赫



2

好了,您可以每晚在源代码库上运行一个克隆检测器。

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

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

理想情况下,您需要的是上面的方法,但是能够找到允许变异相对任意的克隆,例如,用表达式替换变量,用语句替换语句等。

我们的CloneDR克隆检测器可用于Java,C#,C ++,COBOL,VB.net,VB6,Fortran和其他多种语言。可以在以下位置看到它:http : //www.semdesigns.com/Products/Clone/index.html

除了能够处理多种语言外,CloneDR引擎还可以处理各种输入编码样式,包括ASCII,ISO-8859-1,UTF8,UTF16,EBCDIC,多种Microsoft编码和(日语)Shift- JIS。

该站点有几个克隆检测运行示例报告,其中一个针对C ++。

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


1

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


感谢您的链接。我一定会看的。更好的是,有一个日语版本(除我以外,该项目上的所有其他开发人员都是日语)
David Dibben

1

查找“完全相同”的代码段相对容易,已有的工具已在执行此操作(请参阅其他答案)。

有时候这是一件好事,有时却不是。如果做得太“精细”,它可能会缩短开发时间;例如,尝试重构大量代码,您就失去了目标(并可能破坏了里程碑和时间表)。

更加困难的是,在没有适当文档的情况下,找到执行相同功能但具有不同(但相似)输入和/或算法的功能/方法。

如果您必须使用两种或不同的方法来完成相同的事情,而程序员尝试修复一个实例却忘记(或不知道它们存在)来修复另一个实例,则可能会增加软件的风险。


3
……实际上,如果实现方式不同,您将无法检测到两段代码执行相同的操作。有图灵机挡着您。
艾拉·巴克斯特

1
“更困难的是找到在没有适当文档的情况下执行相同操作但具有不同(但相似)输入和/或算法的功能/方法”。对。如果他们做相同的事情,则应给它们命名相同,因为该名称应首先说明为什么该代码存在。因此,第一步可能是确保正确命名和记录所有功能/方法。如果名称真正描述了它的作用,相似性和身份将很快变得显而易见。
MickeyfAgain_BeforeExitOfSO 2010年

麻烦的是,即使是“做同样的事情”的甲骨文(我认为它比终止甲骨文还强大得多?)也无法帮助您确定两个名称是否表达(或打算表达)相同的想法。(除此之外,还会出现很多误报。)
SamB 2012年




0

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

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

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


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.