Лучше всего достичь желаемого результата как можно меньше кодовой базы. Меньшее количество сущностей в кодовой базе, тем легче и дешевле – это ознакомиться с ним, поддерживать его и построить.
Однако, как проект, и его команда растут, так и делает риск случайно введения идентичных или аналогичных произведений кода. Даже больше с итерациями автоматического поколения кода.
Сухой Является ли проект, который я построил, чтобы определить такие подобные произведения (хорошо, хорошо, и играть с haskell).
Это не тривиальная задача, чтобы определить детерминированно, что два (потенциально разные) кусочки кода идентичны, что означает, что они всегда дают один и тот же выход для одного и того же ввода. На самом деле нужно сделать доказательство для такого претензии или его отрицания.
Другой подход основан на эвристике. Это путь, выбранный для сухого. Такой подход имеет свои недостатки: можно легко создать две функции, которые могут обмануть любой набор метрик, и все же доказывают функции, которые будут идентичными. И все же при создании проекта упомянутая уязвимость обычно может быть благополучно игнорирована. Из-за всех лучших практик, соглашений о именах, направляющих стилях, автоматических синтаксических тестах и т. Д. Вполне вероятно, что одинаковые функции будут иметь одинаковые имена, артия, заявления, их количество и глубину. Таким образом я решил дать этот подход попробовать.
Набор метрик рассчитывается для каждой уникальной пары функций. Каждая метрика связана с диапазоном [0; 1]. Вот сами метрики.
Левенштейн Расстояние между названиями двух функций. Точнее,
1/(1 + LD)
где Л.Д. Левенштейн расстояние.Функции «Разница в арифме»: одна, если оба имеют нулевую активность, в противном случае разделение меньшего значения на более высоком.
Функции Сектующие отличия: То же самое Заявления считаются на каждом уровне глубины и рассматриваются отдельно от выступлений различных видов, также учитываются уникальные заявления. Глубё чем менее важно разницу. Более уникальными заявлениями любая из двух функций, тем менее аналогичным функциям (и наоборот).
Функции «Сектующие функции Общая разница всчитывании, подсчитано в моде, похожее на ARITY: One, если оба имеют нулевые операторы, в противном случае подразделение меньшего значения на более чем больше.
Наконец, для каждой пары функций вышеуказанные оценки умножены на вектор весов. Тогда среднее значение значений рассчитывается, и это балл сходства данной функциональной пары.
Можно удивляться, почему нам понадобится четвертая метрика (общее количество отличия отсчета заявлений), если там уже третий (учета разницы в количестве отчетов, сгруппированные по типу оператора и уровнем глубины). Если тел функций состоят из подобных заявлений, четвертая метрика, возможно, чрезмерная. Однако, если они состоят из разных заявлений, там все еще могут быть или могут быть недобросовестности в количестве заявлений, используемых для их определения. Четвертая метрическая учетная запись для этого.
Последняя метрика (как четыре выше) связана с [0; 1] Где 1 одинаково, и 0 совершенно другой.
Я казнил сухость по ряду REPO и создал эту визуализацию с Python:
Интересно, что большинство подобных функций являются теми, что с одинаковым общем подсчета заявлений. Это просто следствие того, как рассчитан счет ( см. Вес веса ). Также стоит отметить, что есть функции с сотнями утверждений. Например, вот Vue CreatePatchfunction
с 3831 заявлениями.
Vue – это достаточно большой, чтобы проиллюстрировать весь спектр возможностей. Давайте сначала посмотрим на одни и те же функции, есть довольно ряд.
Сначала вот createoncehandler
для Одна платформа и за другой Отказ
Тогда Гендата
для класс и Стиль Отказ Это своеобразный случай. Согласно метрикам, эти функции абсолютно одинаковы (с оценкой 1.0
). Однако на практике, однако они не являются: строковые шаблоны немного отличаются, поэтому делайте объектные имена свойств. Это технически можно объяснить такие виды различий. Делает ли это практический смысл – это другой вопрос.
Есть и другие подобные случаи Гендата
такие как этот Отказ Всего шесть уникальных пар сдача
S был найден. Это дает нам четыре разных Гендата
Функции, аналогичные друг другу (поскольку пары уникальны, а порядок в паре незначительно).
Еще один пример пары подобных функций – генерация
. Я бы предположил этот связано с рендерингом на стороне сервера, а этот для стороны клиента.
Хорошо, как насчет почти Подобные функции. Следующая пара функций имеет оценку сходства 0,952695949955943
и отчет о выписке 105
и 100
Соответственно: Трансформировать
и Трансформировать
Отказ Обратите внимание, как в последнем случае это тестируется ли StaticClass
оценивает правда
, пока Staticstyle
не проверяется, хотя то, как они извлекаются, одинаково: использование getandremoveattr
Отказ
В общей сложности 167 331 уникальных пар для репо , с парой наименее подобных функций, имеющих счет 0,002267573696145
Отказ Я приглашаю читателя видеть для себя, что эти функции.
Как показано выше, Сухой Может использоваться не только для идентификации аналогичных функций для того, чтобы аннотация их выяснить и, таким образом, облегчить любое повторение в кодовой базе, но и для точечного несоответствия, которое может помочь обнаружить ошибку. Надеюсь, вы найдете инструмент полезным. Пожалуйста, не стесняйтесь попробовать, укажите любые проблемы и потенциальные способы его улучшения.
Спасибо за чтение!
Оригинал: “https://dev.to/ch3rn0v/how-to-identify-similar-pieces-of-code-4k67”