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

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

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

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

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

13 ответов

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

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

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

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

Для начала вывод "Текст" должен быть в порядке, но вы захотите отобразить результаты в удобной для пользователя форме, для чего я использую скрипт perl для генерации HTML-файлов из вывода "xml" CPD. Доступ к ним можно получить, разместив их на коте, где находится 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>

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

Эти пакеты Debian, кажется, делают что-то вроде этого:

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

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

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

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

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

Приведенный выше 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: Теперь обрабатывает все C++14.

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

Это поддерживается Гудзоном (например, CPD).

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

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

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

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

ConQAT - отличный инструмент для анализа кода на C++. Можно найти дубликаты, игнорируя пробелы. Имеет очень удобный графический интерфейс и консольный интерфейс. Из-за его гибкости его нелегко настроить. Я нашел этот пост очень полезным для настройки проекта C++.

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

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

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

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

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

Другие вопросы по тегам