Насколько хорошо статический анализ кода работает с Spring и другими абстракциями?

Я нахожусь в ситуации, когда мне необходимо приложить хоть какие-то усилия для удаления никогда не использованного кода из моего исходного кода. Общее предпочтение - использовать инструмент статического анализа кода. Нам повезло с этим в других проектах, но люди, о которых я слышал, в основном разработчики C/C++, работающие над кодом на уровне устройства.

Я веб-разработчик, работающий над системой Java EE. Излюбленным инструментом анализа является Coverity Prevent, хотя я мог бы, вероятно, выступить за что-то еще, если бы убедительно обосновал, что это больше соответствует технологии, с которой мы разрабатываем.

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

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

Какой опыт у этого сценария? Удалось ли вам получить пользу от инструмента статического анализа кода, когда в вашей архитектуре использовалось много абстракций? Было ли что-то, что вам нужно было сделать, чтобы заставить его работать с минимумом ложных срабатываний?

4 ответа

Ранее я работал в Coverity, над продуктом статического анализа Java.

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

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

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

Инструмент для тестирования Java, который может собрать эти данные для вас, можно найти здесь.

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

В общем, обнаружение мертвого кода X требует доказательства того, что нет условия, при котором X вызывается. Это трудно (теоретически невозможно), когда сталкиваешься с машиной Тьюринга и выражениями IF вида

 if (Turing(..)) then call X();

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

Однако во многих случаях "мертвый код" - это на самом деле просто код, который просто не имеет возможности вызвать его ("деактивный код" на языке FAA). То есть, пока X определен, просто и косвенно не существует ни одного вызова X (или доступа, если X является элементом данных) нигде в системе. Это проще для инструментов статического анализа обнаруживать с запутанной сложностью в Java динамической загрузки и отражения классов (что делает проблему деактивного анализа кода невозможной перед лицом неизвестных, но загружаемых классов).

Игнорируя эти сложности, можно найти инструменты статического анализа, которые обнаруживают неактивный код в больших системах Java и сообщают о нем. Такой инструмент должен обрабатывать всю систему Java одновременно, потому что в противном случае ссылка может существовать в одном модуле, не включенном в анализ. Мы создали "неактивный" детектор кода, а средство удаления может даже предоставить вам исходный код со всем автоматически удаленным деактивированным кодом, а также сообщить о том, на что нет ссылок. Вы просматриваете отчет и решаете, хотите ли вы использовать очищенный код или добавить доступ к явно неиспользованному объекту.

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

И я сомневаюсь, что наличие мертвого кода стоит больше, чем это.

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

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

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