Вебинар: Использование статических анализаторов кода при разработке безопасного ПО - 19.12
В этой статье мы рассмотрим основные возможности SonarQube — платформы для непрерывного анализа и измерения качества кода, а также обсудим достоинства методики оценки качества кода на основе метрик SonarQube.
Наша компания занимается разработкой статического анализатора кода PVS-Studio. Мы убеждены, что выбор подходящей методологии разработки и следование ей, применение доказавших свою эффективность методик и инструментов существенно повышает вероятность того, что код будет написан правильно, и конечный продукт будет соответствовать требуемым стандартам качества. Одной из таких методологий является использование статического анализа исходного кода. Статический анализ, применяемый вместе с другими метриками кода, позволяет оценить текущее состояние кодовой базы, динамику этого состояния, возможные риски при реализации проекта.
Для начала расскажу вкратце о представлении результатов анализа PVS-Studio. Результаты работы нашего статического анализатора PVS-Studio сохраняются в формате xml. Список сообщений об обнаруженных ошибках можно открыть прямо в окне Microsoft Visual Studio или в отдельной утилите Standalone, и работать с этими ошибками, используя возможности навигации по коду, сортировки, фильтрации, подавления ложных срабатываний и т. д.
Список найденных ошибок в формате xml можно преобразовать в один из форматов, удобных для чтения, например, html. Такие отчёты с результатами анализа можно рассылать всем заинтересованным участникам проекта по почте. Другой способ оповещения участников проекта — рассылка списков ошибок тем разработчикам, которые их допустили. Для этого пользователи могут использовать специальные утилиты, поставляемые в дистрибутиве PVS-Studio.
Говоря о возможностях PVS-Studio, следует упомянуть о функциональности для массового подавления диагностических сообщений. Если статический анализ был внедрен на поздних этапах жизненного цикла приложения, когда объем кодовой базы достиг большого размера, инспекция кода может привести к обнаружению большого количества ошибок. Возможно, в данный момент времени у команды отсутствуют ресурсы, необходимые для исправления всех ошибок. В этом случае разработчики могут скрыть все сообщения, выданные на текущей ревизии кода, и сконцентрироваться на ошибках, найденных во вновь написанном или модифицированном коде.
Динамику количества ошибок, найденных PVS-Studio, можно получить, используя функциональность Analysis Statistics плагина PVS-Studio для Microsoft Visual Studio или утилиты Standalone:
Перечисленные способы представления результатов работы нашего статического анализатора, однако, существуют сами по себе и не связаны с другими метриками кода, такими как количество строк кода, цикломатическая сложность, количество ошибок на 1000 строк кода, уровень покрытия кода модульными тестами, дублирование и так далее. Отчет о найденных ошибках после очередного анализа и количество этих ошибок не дает ответов на вопросы: много у нас ошибок или мало? Как динамика количества ошибок связана с ростом кодовой базы? Улучшается или ухудшается качество кода? И, наверное, самый главный вопрос менеджеров: когда все будет работать (сколько времени потребуется, чтобы устранить ошибки)? Эти вопросы заставили нас задуматься о том, как придать отчетам PVS-Studio большую ценность и информативность.
Почему же полезно собирать и контролировать метрики кода? Невозможно улучшить то, что вы не измеряете. Предположим, какая-то команда не собирает метрики кода. С развитием проекта кодовая база может становиться все хуже и хуже, и долгое время никто этого даже не заметит, пока в какой-то момент объем технического долга не достигнет такого размера, что поддержка и добавление новой функциональности будет стоить дороже и дороже. Если бы команда постоянно отслеживала метрики кода, она бы видела динамику состояния своего проекта и, по достижению определенных пороговых значений, начала бы бить тревогу.
Далее, допустим, команда осознала проблему и убедила своего менеджера в том, что необходимо потратить ресурсы на улучшение качества кода. Менеджер, в свою очередь, задаст команде несколько простых вопросов: сколько времени понадобится на это команде? Какие части проекта необходимо улучшить? Сколько багов вы собираетесь исправить? По каким критериям вы оцените, что качество кода достигло требуемого уровня, и можно снова вернуться к разработке новой функциональности? Использование метрик позволит ответить на все эти вопросы. Если перед началом работ по улучшению качества кода команда зафиксирует текущее состояние кода по каждому компоненту продукта и определит пороговые значения для каждой метрики, достижение которых позволит с определенной степенью уверенности заявить, что код продукта стал качественным, можно спрогнозировать дату окончания работ и остановиться тогда, когда определенные пороговые значения будут достигнуты. Так, например, команда сможет показать менеджеру, что после окончания работ по повышению качества кода уровень покрытия модульными тестами достиг 90%, следование стандартам кодирования, принятым в компании, достигло 95%, а дублирование кода сократилось до 5%, и т.д.
SonarQube — это платформа с открытым исходным кодом, предназначенная для непрерывного анализа и измерения качества кода. SonarQube предоставляет следующие возможности:
Впечатляющий список, не так ли? Вы можете сами познакомиться с возможностями SonarQube и попробовать его в действии, перейдя по ссылке https://sonarqube.com/. Компания SonarSource предоставляет этот сервис для анализа open source-проектов, и, если у вас есть открытый проект на GitHub, вы можете загрузить его в сервис https://sonarqube.com/ и пользоваться отчетами SonarQube для котроля качества кода вашего проекта.
Мы тщательно изучили возможности платформы SonarQube и решили, что эти возможности могут быть интересны нашим клиентам. Поэтому мы приняли решение о разработке плагина для импорта результатов анализа PVS-Studio.
Приблизительно в это же время один из наших клиентов выразил заинтересованность во внедрении централизованного хранилища различных метрик кода. Клиент разрабатывает очень крупный (более 10 миллионов строк кода) и долгосрочный (более 15 лет активной разработки) проект. Естественно, в таком проекте очень много унаследованного кода и связанных с ним скелетов в шкафу, и в этом случае, на мой взгляд, совершенно необходимо разработать и внедрить набор метрик, позволяющих оценить состояние кода проекта и динамику изменений этого состояния во времени. Естественно, наш клиент давно принял решение о сборе и анализе метрик, и внедрил различные утилиты для мониторинга показателей качества кода, таких как: покрытие кода модульными тестами, результаты прогона тестов, дублирование блоков кода, следование принятым стандартам кодирования, плотность комментариев в коде и т.д. Параллельно со сбором этих метрик ежедневно выполнялся статический анализ кода. Использование большого количества утилит приводило к усложнению конфигурации сервера непрерывной интеграции, написанию дополнительных скриптов для преобразования результатов работы каждой утилиты в удобный для представления вид и объединения всех показателей в единый отчет. Такой подход требовал значительных ресурсов на создание и поддержку этой системы отчетности.
Исходя из потребностей клиента и нашего исследования возможностей платформы SonarQube, мы предложили внедрить эту платформу. Что и было сделано. В рамках задачи по внедрению был реализован плагин для SonarQube, позволяющий импортировать в SonarQube результаты анализа PVS-Studio. Процесс развертывания SonarQube и его интеграции с имеющимся окружением (сборочная система, сервер непрерывной интеграции, система контроля версий) не вызвал затруднений благодаря логичным механизмам настройки и большого количества подробной документации. Были настроены виджеты, позволяющие оценивать как состояние портфолио проектов клиента в целом, так и состояние каждого проекта в отдельности, настроены Quality Profiles и Quality Gates (об этих механизмах SonarQube я расскажу ниже) согласно потребоностям клиента, автоматическое назначение задач на исполнителей, рассылка уведомлений всем заинтересованным лицам.
В результате внедрения SonarQube клиент получил централизованную систему хранения и отображения метрик кода, позволяющую оценивать и прогнозировать риски проекта. Переход от отдельных инструментов к централизованной системе контроля качества кода не только упрощает развертывание и поддержку этой системы, но и позволяет совершить качественный скачок в сфере управления проектами, предоставляя всем заинтересованным участникам средства для мониторинга состояния проекта и принятия взвешенных решений. После тестовой эксплуатации клиент принял решение о включении SonarQube в действующий набор инструментов ALM (Application Lifecycle Management).
Следует отметить, что SonarQube, благодаря своим широким возможностями интеграции с другими инструментами, легко может стать неотъемлемой частью вашего фреймворка ALM. С помощью плагинов в SonarQube можно добавить поддержку Git, SVN, Mercurial, Team Foundation Version Control, ClearCase, настроить авторизацию через LDAP, GitHub, Bitbucket, Azure Active Directory, импортировать результаты работы сторонних анализаторов. Плагины SonarLint для IntelliJ IDEA, Eclipse и Visual Studio позволяют анализировать код в режиме реального времени в вашей любимой IDE, используя правила, определенные в профиле SonarQube. Также доступна интеграция с Team Foundation Server и Visual Studio Team Services. Вы можете запустить анализ кода и импорт данных в SonarQube прямо из сборочного процесса в этих системах, или, например, управлять состоянием сборок в Team Foundation Server и Visual Studio Team Services с помощью Quality Gates (индикаторов качества сборки), настронных в SonarQube: если код не удовлетворяет требованиям Quality Gate, сборка будет считаться неудавшейся. Таким образом, разработчики SonarQube стремятся сделать свой продукт максимально открытым и позволить командам разработчиков интегрировать SonarQube в их окружение.
Для каких же проектов и команд целесообразно внедрять SonarQube? Я считаю, что для относительно короткосрочных проектов (не более 2 - 3 месяцев), которыми занимаются небольшие команды (не более 5 человек), инвестиции во внедрение SonarQube в процесс разработки могут не оправдаться. Как правило, такие проекты не требуют больших затрат на поддержку продукта. Для таких проектов я бы рекомендовал ограничиться отдельными инструментами для контроля состояния кода проекта: статический анализатор, контроль покрытия кода тестами, соответствие стандартам кодирования и т.д., которые команда привыкла использовать.
На крупных проектах, требующих значительных ресурсов, с продолжительным жизненным циклом, внедрение платформы SonarQube в процесс разработки оправдано. Причем внедрение SonarQube может принести пользу на любой стадии развития проекта. Оптимальная, на мой взгляд, стратегия - это внедрение SonarQube на ранних этапах цикла разработки, что позволит команде с самого начала анализировать отчеты о контроле качества и быть уверенными в том, что соблюдаются заданные стандарты качества кода. Внедрение SonarQube на более поздних этапах разработки потенциально может потребовать больших затрат на улучшение качества кода. Так, например, может выясниться, что статический анализ обнаружил большое количество потенциальных ошибок, присутствует большой объем технического долга, код не покрыт тестами, публичные API не документированы и т.д. Тем не менее, выявление рисков продукта на любой стадии жизненного цикла позволяет правильно отреагировать на эти риски и спланировать действия по их минимизации.
Например, команда может договориться, что при изменении какого-то участка кода в рамках разработки новой функциональности будет ликвидирован весь технический долг в этом коде. Инвестиции в устранение найденных недостатков позволят в дальнейшем снизить стоимость поддержки продукта и разработки нового функционала. Также, если продукт давно присутствует на рынке, и несмотря на то, что инспекция качества кода выявила большое количество проблем, поведение в продукционной среде достаточно стабильно и в текущий момент времени нет достаточных ресурсов для улучшения качества кодовой базы, можно отложить эту инвестицию. SonarQube предоставляет возможность сфокусироваться на проблемах, появившихся в новом коде. Эта функциональность похожа на функциональность массового подавления сообщений в PVS-Studio.
В основе модели качества SonarQube лежит реализация методологии SQALE (Software Quality Assessment based on Lifecycle Expectations) с определенными дополнениями. Как известно, методология SQALE фокусируется в основном на сложности поддержки кода (maintainability) и не учитывает риски проекта. Например, если сегодня в проекте обнаружилась критическая проблема безопасности, строгое следование методологии SQALE обязывает вас устранить все уже существующие проблемы с надежностью (reliability), возможностью изменений (changeability), тестируемостью (testability) и т.д., и только затем вернуться к новой критической проблеме. На самом деле, если потенциальные проблемы существуют в коде давно и не проявляют себя в виде пользовательских баг-репортов, гораздо важнее сфокусироваться на исправлении новых багов.
С учетом этого, разработчики SonarQube модифицировали модель качества, основанную на SQALE, чтобы акцентировать внимание на следующих важных моментах:
Стандартный Quality Gate SonarQube использует следующие значения метрик для определения того, что код успешно прошел проверки:
Команда Sonar определила семь смертных грехов разработчиков, увеличивающих технический долг:
Платформа SonarQube предназначена для того, чтобы помогать бороться с этими семью грехами.
Рассмотрим более подробно основные возможности SonarQube.
На главной странице SonarQube вы видите список проектов, добавленных в систему, с краткой статистикой по каждому проекту: версия сборки, количество строк кода, количество багов, уязвимостей и признаков "кода с душком", дата последнего анализа:
Содержимое главной страницы можно настроить под ваши цели с помощью большого набора встроенных виджетов, позволяющих визуализировать состояние кода проектов в SonarQube.
Для получения более детальной информации о состоянии проекта перейдем на страницу метрик проекта:
Здесь представлена информация о следующих метриках кода: Reliability (Надежность), Security (Безопасность), Maintainability (Поддерживаемость), Coverage (Покрытие тестами), Duplications (Дублирование), Size (Размер кодовой базы), Complexity (Цикломатическая сложность), Documentation (Документирование кода) и Issues (Ошибки).
Перейдя к метрике Reliability, мы получаем информацию об общем количестве обнаруженных багов и новые баги, обнаруженные во время последнего анализа, рейтинг надежности кода по шкале от A до E, где E - наихудший рейтинг, свидетельствующий о том, что был найден по крайней мере один blocker баг, а также время, необходимое на устранение всех найденных ошибок:
Платформа SonarQube позволяет анализировать метрики кода сверху вниз, от уровня проекта в целом до отдельных модулей и файлов. Так, например, если вы кликните на рейтинг надежности (Reliability Rating), вы увидите список файлов проекта, отсортированных по возрастанию рейтинга надежности. Это позволит сфокусироваться на наиболее проблемных участках кода:
Затем вы можете перейти к файлу с исходным кодом и к конкретным участкам кода, в которых обнаружены ошибки:
Такая навигация сверху вниз доступна и для других метрик.
На странице метрики Security доступна информация об общем количестве уязвимостей, новых уязвимостях, рейтинге безопасности (также по шкале от A до E), и времени, которое потребуется на устранение уязвимостей:
Страница Maintainability содержит информацию о техническом долге в проекте:
Благодаря навигации "сверху вниз" вы можете перейти к списку файлов, отсортированных по количеству обнаружений кода с душком:
и затем непосредственно к коду, который требует внимания:
На странице Coverage представлена информация о покрытии кода тестами:
Страница Duplications содержит информацию о дублировании кода в проекте:
С помощью этой метрики вы легко можете обнаружить повторяющиеся строки, блоки кода и даже целые файлы:
Страница Size содержит информацию о размере проекта: количество строк кода, выражений, функций, классов, файлов и директорий:
На странице Complexity представлена информация о суммарной цикломатической сложности проекта, а также о средней сложности функций и файлов:
Страница Documentation предоставляет информацию о комментариях в коде: отношение строк с комментариями к общему количеству строк в проекте, количество строк с комментариями, количество публичных API и уровень документирования публичных API:
Последняя вкладка в разделе метрик проекта - Issues - содержит общее количество найденных проблем в коде (сумма количества багов, уязвимостей и code smells), а также распределение проблем по состоянию: открытые, переоткрытые, подтвержденные, ложные срабатывания и won't fix:
После анализа метрик кода посмотрим, как SonarQube позволяет работать с найденными проблемами в коде. Для этого перейдем в раздел Issues:
Здесь представлены все найденные проблемы в коде с широкими возможностями фильтрации, что позволяет сфокусироваться на наиболее важных проблемах. Следует отметить, что SonarQube позволяет сохранять настройки фильтров, чтобы повторно их использовать.
По двойному клику на сообщении об ошибке вы можете перейти к коду, в котором была найдена проблема. Также доступно детальное описание ошибки и рекомендации, как ее исправить:
Обратите также внимание, что, благодаря интеграции с системами контроля версий, видно, кто и когда внес изменения в код, вызвавшие срабатывание анализатора:
Интеграция с системами контроля версий позволяет также автоматически назначать баги в SonarQube на тех разработчиков, которые их допустили. Также вы можете назначать баги на разработчиков вручную, изменять их тип (bug, vulnerability или code smell), важность, теги, добавлять комментарии. Для большего удобства использования доступна функция массового изменения багов:
Диагностические правила (Rules), профили качества (Quality Profiles) и границы качества (Quality Gates) - ключевые понятния платформы SonarQube. Каждый плагин для SonarQube, осуществляющий статический анализ кода, содержит репозиторий с описанием диагностических правил, которые этот плагин выполняет. Нарушения этих правил используются для определения технического долга в коде и вычисления времени на устранение проблем. Для удобства использования правила объединяются в профили качества (Quality Profiles). По умолчанию, SonarQube создает дефолтный профиль качества для каждого поддерживаемого языка, но вы можете создавать свои профили качества с тем набором диагностических правил, которые вам могут быть полезны. Например, для анализа критически важных проектов, требования к качеству кода которых самые строгие, можно определить профиль качества, содержащий все доступные диагностики, а для менее критичных проектов можно определить менее строгий профиль качества, содержащий только серьезные ошибки, что позволит не отвлекаться на незначительные code smells.
Quality Gate - это индикатор соответствия (или несоответствия) кода проекта заданным пороговым значениям метрик. По умолчанию, все проекты, добавленные в SonarQube, используют стандартный quality gate, в котором определены следующие метрики и их пороговые значения:
Исходя из ваших собственных требований к качеству исходного кода, вы можете изменить стандартный quality gate или создать новый, добавляя или удаляя те метрики и их пороговые значения, которые представляют для вас интерес.
Для импорта результатов анализа в SonarQube мы разработали плагин sonar-pvs-studio-plugin. Использование плагина позволяет добавлять сообщения, найденные анализатором PVS-Studio, в базу сообщений сервера SonarQube. Плагин содержит репозиторий с описанием диагностик, которые выполняет наш статический анализатор. После того, как вы добавите наш плагин в SonarQube, вы увидите репозиторий с названием PVS-Studio для языков C, C++ и C#:
Диагностические сообщения PVS-Studio в репозитории плагина сопровождаются подробными описаниями ошибок с примерами кода и рекомендациями по устранению проблемы:
После анализа кода проекта и импорта результатов в SonarQube, с помощью фильтров вы можете, например, выбрать все неисправленные проблемы, найденные PVS-Studio:
Чтобы добавить результаты анализа PVS-Studio в SonarQube, достаточно установить плагин sonar-pvs-studio-plugin, добавить диагностики PVS-Studio из репозитория плагина в Quality Profile и передать путь до файла отчета PVS-Studio в свойстве sonar.pvs-studio.reportPath при запуске сканера SonarQube.
Для анализа проектов MSBuild разработчики SonarQube рекомендуют использовать SonarQube Scanner for MSBuild. Этот сканер представляет из себя обертку над стандартным сканером SonarQube и облегчает процесс создания конфигурационного файла сканера sonar-project.properties, автоматически добавляя в него модули (проекты в решении) и записывая пути до исходных файлов, которые необходимо проанализировать.
Однако мы столкнулись с важными с нашей точки зрения ограничениями сканера SonarQube Scanner for MSBuild.
Во-первых, при анализе C/C++ проектов этот сканер добавит в список файлов для анализа только те файлы, которые добавлены в свойства ClCompile и ClInclude проектного файла .vcxproj. Если, например, заголовочный файл не включен явно в проект и подключен в коде одного из исходных файлов, этот файл будет проигнорирован, и результаты анализа этого файла будут отсутствовать в SonarQube.
Во-вторых, SonarQube Scanner for MSBuild не добавляет для анализа исходные файлы, расположенные выше по дереву каталогов, чем каталог, в котором находится проектный файл. Сообщения для таких файлов будут также отсутствовать в SonarQube.
Исходя из этих ограничений, для импорта результатов анализа PVS-Studio мы рекомендуем использовать стандартный сканер SonarQube. Использование этого сканера предполагает создание конфигурационного файла sonar-project.properties вручную. Использование и настройка сканера описаны в статье Analyzing with SonarQube Scanner.
По умолчанию, сканер SonarQube индексирует исходные файлы для анализа, расположенные по дереву каталогов ниже, чем файл решения (.sln) либо проекта (.vcxproj/.csproj). Для анализа проектов со сложной структурой, где исходные файлы могут находиться выше по дереву каталогов, чем файл решения или проекта, в свойстве sonar.projectBaseDir нужно указать наивысший общий каталог для всех исходных файлов (в крайнем случае, это может быть корень диска), и в свойстве sonar.sources затем перечислить директории, в которых следует искать исходные файлы для анализа (либо полные пути до исходных файлов).
Процесс добавления путей до исходных файлов в свойство sonar.sources для больших проектов может быть достаточно трудоемким, а с учетом всех подключаемых заголовочных файлов - и нетривиальным. Чтобы облегчить эту задачу, мы реализовали специальный режим работы нашего анализатора, позволяющий автоматически создавать конфигурационные файлы для сканера SonarQube.
При разработке нашего статического анализатора мы фокусируемся на поиске ошибок в коде, и не поддерживаем поиск потенциальных уязвимостей и code smells, поэтому при использовании нашего плагина для SonarQube метрики Security и Maintainability не будут заполнены. Также следует отметить, что в текущей версии нашего плагина не реализовано вычисление Duplications, Complexity и Documentation.
В этом обзоре я попытался показать, как SonarQube позволяет внедрить и применять практики контроля качества кода на основе метрик. Как сказал Питер Друкер (или, возможно, это был Уильям Деминг): if you can't measure it, you can't improve it. Регулярный сбор метрик кода, анализ их изменения с течением времени позволяет обнаруживать, что технический долг накапливается, поддерживаемость кода снижается, что приводит к увеличению стоимости разработки нового функционала и повышению рисков, связанных с поставкой новых версий продукта. Приведу цитату из книги "Программист-прагматик. Путь от подмастерья к мастеру" Эндрю Ханта и Дэвида Томаса:
"Не оставляйте "разбитые окна" (неудачные конструкции, неверные решения или некачественный текст программы) без внимания. Как только их обнаружите, чините сразу. Если нет времени на надлежащий ремонт, забейте окно досками. Наверняка вы сможете закомментировать ошибочный фрагмент или вывести на экран сообщение "В стадии разработки", или использовать фиктивные данные. Необходимо предпринять хотя бы малейшее действие, чтобы предотвратить дальнейшее разрушение, и показать, что вы контролируете ситуацию.
Мы видели, как безошибочные, функциональные системы быстро портились, как только окна начали разбиваться. Существуют и другие факторы, которые вносят свой вклад в порчу программ, и мы коснемся некоторых из них далее, но небрежность ускоряет порчу быстрее, чем любой другой фактор.
Вы можете подумать, что ни у кого не будет времени обойти "разбитые окна" проекта и отремонтировать их. Если вы продолжаете думать подобным образом, тогда вам лучше спланировать приобретение мусорного контейнера или переехать в другой район города. Не давайте энтропии победить себя.".
Платформа SonarQube позволяет обнаруживать такие "разбитые окна". Используя SonarQube, вы получите доступ к консолидированным отчетам о состоянии кода проекта, смотреть, как это состояние меняется с течением времени, сможете исследовать обнаруженные проблемы методом анализа "сверху вниз", от значения интересующей вас метрики для всего проекта в целом до конкретного участка кода прямо в окне браузера. SonarQube также предоставляет оценку времени, необходимого для устранения проблем в коде. Таким образом, если в вашем проекте накопился большой объем технического долга, вы всегда можете сказать, сколько вам нужно времени для его устранения.
Из интересных и полезных особенностей SonarQube хочу также отметить его широкие возможности для интеграции с другими инструментами, что делает его частью вашего ALM-фреймворка, и возможности расширения сушествующего функционала благодаря использованию сторонних плагинов. И вся эта мощь и удобство доступны под свободной лицензией бесплатно. Если вы используете статический анализатор PVS-Studio, наш плагин позволит вам импортировать результаты анализа в SonarQube, чтобы использовать его возможности для исследования проблем с качеством кода.
Если возможности платформы SonarQube вас заинтересовали, попробуйте ее в своем окружении. Установка SonarQube очень проста и заключается лишь в извлечении файлов дистрибутива из архива и запуске исполняемого файла под вашу операционную систему.
Также вы можете проверить свои проекты, написанные на языках C/C++ или C#, с помощью статического анализатора PVS-Studio.
0