Как обнаружить дублирование кода при разработке?
У нас довольно большая кодовая база, 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, кажется, делают что-то вроде этого:
сходство тестер (также известный как программное обеспечение и тестер сходства текста SIM)
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, который может легко запускаться как часть вашей системы сборки.