Как обнаружить дублирование кода во время разработки?

У нас есть довольно большая база кода, 400K LOC на С++, а дублирование кода - это что-то вроде проблемы. Существуют ли какие-либо инструменты, которые могут эффективно обнаруживать дублированные блоки кода?

В идеале это будет то, что разработчики могли бы использовать во время разработки, а не просто запускать время от времени, чтобы увидеть, где проблемы. Было бы неплохо, если бы мы могли интегрировать такой инструмент с CruiseControl, чтобы дать отчет после каждой проверки.

Недавно я просмотрел Duploc, он показал хороший график, но для его использования требуется среда с небольшим количеством строк, что делает автоматически запускать его довольно сложно.

Бесплатные инструменты были бы хороши, но если есть хорошие коммерческие инструменты, мне также было бы интересно.

Ответ 1

Simian обнаруживает дублирующий код в проектах на С++.

Обновление: также работает с Java, С#, C, COBOL, Ruby, JSP, ASP, HTML, XML, Visual Basic, Groovy исходным кодом и даже текстовыми файлами

Ответ 2

Я использовал PMD Copy-and-Paste-Detector и интегрировал его в CruiseControl, используя следующую оболочку script (обязательно для получения pmd-jar в пути к классам).

Наша проверка выполняется в ночное время. Если вы хотите ограничить вывод списком только файлов из текущего набора изменений, вам может понадобиться какое-то пользовательское программирование (идея: проверьте все и перечислите только дубликаты, в которых задействован один из измененных файлов. Вы должны проверить все файлы, потому что изменение может использовать некоторый код из неизменяемого файла). Должно быть выполнимо с помощью вывода XML и анализа результата. Не забудьте опубликовать, что script, когда это было сделано;)

Для начала вывод "Текст" должен быть в порядке, но вы хотите отображать результаты удобным для пользователя способом, для которого я использую perl script для генерации HTML файлов из вывода "xml" CPD, Доступ к ним можно получить, отправив их в tomcat, где находится информация о круизных сообщениях jsp. Разработчики могут просматривать их оттуда и видеть результаты их грязного взлома:)

Он работает довольно быстро, менее 2 секунд на 150 KLoc-коде (пустые строки и комментарии не учитываются в этом номере).

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>

Ответ 3

duplo представляется реализацией C алгоритма, используемого в Duploc. Его легко компилировать и устанавливать, и, хотя параметры ограничены, кажется, что более или менее работает из коробки.

Ответ 4

Посмотрите проект PMD.

Я никогда не использовал его, но всегда хотел.

Ответ 5

Ну, вы можете запустить детектор клонов на вашем источнике кодовая база каждую ночь.

Многие детекторы клонов работают, сравнивая исходные строки, и может найти только точный дубликат кода.

CCFinder, выше, работает, сравнивая язык токены, поэтому он не чувствителен к пробелу изменения. Он может обнаруживать клоны, которые являются вариантами исходного кода, если имеется только один токен изменения (например, изменить переменную X на Y в клон).

В идеале, что вы хотите, это выше, но способность найти клоны, где вариации допускаются относительно произвольными, например, заменить переменную выражением, утверждение блоком и т.д.

Наш клон-детектор CloneDR делает это для Java, С#, С++, COBOL, VB.net, VB6, Fortran и разнообразия других языков. Это можно увидеть по адресу: http://www.semdesigns.com/Products/Clone/index.html

Помимо возможности управлять несколькими языками, механизм CloneDR способен обрабатывать различные стили ввода, включая ASCII, ISO-8859-1, UTF8, UTF16, EBCDIC, ряд кодировок Microsoft и (японский ) Shift-JIS.

На сайте есть несколько отчетов о запуске проверки клонов, в том числе один для С++.

EDIT Feb 2014: теперь обрабатывает все С++ 14.

Ответ 6

Для моей собственной будущей ссылки эти пакеты Debian, похоже, что-то делают в этом направлении:

Я мог бы поклясться, что у меня установлены другие пакеты (ы), которые могут быть еще более важными, но я не могу их найти в данный момент. (Вот почему я перечисляю свои результаты здесь в этот раз: чтобы дать себе шанс снова найти их!)

P.S. Кажется, что должен быть тег debtags для всех инструментов, связанных с поиском [близкого] дублирования. (Но что бы это называется?)

Ответ 7

CCFinderX - бесплатный (для собственного использования) клонированный детектор кода, который поддерживает несколько языков программирования (Java, C, С++, COBOL, VB, С#).

Ответ 8

Поиск "идентичных" фрагментов кода относительно прост, существует уже существующий инструмент, который уже делает это (см. другие ответы).

Иногда это хорошо, иногда это не так; он может прогнать время разработки, если сделать его на слишком тонком "уровне"; то есть, пытаясь реорганизовать так много кода, вы потеряете свою цель (и, вероятно, повредите свои вехи и графики).

Что сложнее найти несколько функций/методов, которые делают то же самое, но с разными (но схожими) входами и/или алгоритмом без надлежащей документации.

Если вам нужно выполнить два или несколько методов, чтобы сделать то же самое, и программист попытается исправить один экземпляр, но забыть (или не знает, что они существуют), чтобы исправить другие, вы увеличите риск для своего программного обеспечения.

Ответ 9

То же самое (http://sourceforge.net/projects/same/) очень просто, но он работает на текстовых строках вместо токенов, что полезно, если вы используя язык, который не поддерживается одним из искателей поиска fancier.

Ответ 11

Вы можете использовать наш инструмент SourceMeter для обнаружения дублирования кода. Это инструмент командной строки (очень похожий на компиляторы), поэтому вы можете легко интегрировать его в инструменты непрерывной интеграции, такие как CruiseControl упомянутые вами, или Jenkins.

Ответ 12

Существует также Simian, который поддерживает Java, С#, С++, C, Objective-C, JavaScript...

Он поддерживается Хадсоном (например, CPD).

Если вы не являетесь проектом с открытым исходным кодом, вы должны заплатить за Simian.

Ответ 13

TeamCity имеет мощный механизм дублирования кода для .NET и java, который может легко запускаться как часть вашей системы сборки.