Идеальный код: битва при Sonar

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

Команда Parallels работает над своими проектами больше 20 лет. Сотни человек в России, Эстонии, на Мальте, в США, Японии и других странах развивают наше ПО. Коллектив большой, продуктов много (намного больше, чем один всемирно известный Parallels Desktop), репозиторий тоже внушительный.

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

Именно поэтому сложно жить без инструмента, который бы помогал нам в автоматическом режиме следить за качеством кода. Также мы хотели, чтобы наши продукты соответствовали определённым правилам и стилю кодирования. Речь про автоматические метрики, которые можно было бы посчитать (например, сложность кода) и сделать его логику простой для понимания, без излишеств. Это не значит, что мы захотели отказаться от написания сложного кода, просто если существует возможность написать простой и сложный код для одной функциональности, лучше выбрать первое, глядишь и дебажить придется меньше. Так в нашей жизни появился SonarQube.

Sonar здорового человека

SonarQube — это платформа для анализа и измерения качества кода. Что это и с чем ее едят подробно и доступно описано на Хабре: здесь, здесь или здесь.

Справедливости ради, стоит сказать, что автоматизацию мы начинали с дополнительного плагина к Jenkins (Warnings Next Generation). С его помощью можно собирать, агрегировать и визуализировать отчеты различных утилит статического анализа, компиляторов, линтеров. Можно настроить так называемый Quality Gate и посылать уведомления разработчикам о новых проблемах в коде.

Мы начали с ночных проверок, чтобы отчет для разработчиков был готов утром. Но это оказалось не очень удобно и невозможно было понять, смотрел ли разработчик отчет или нет. Можно было попробовать проверять таким образом pull-request’ы (мы до этого не дошли). Но это не очень удобно для разработчиков, потому что ревью в одной системе, а найденные баги в совершенно другой. Было бы здорово иметь возможность видеть найденные проблемы прямо в ревью. Тут то и пришел на помощь SonarQube.

Вообще существует довольно много приятных плагинов для Jenkins:

  1. Ant Plug-in - Ant поддержка.

  2. ChuckNorris Plug-in – Чак Норис показывающий свой вид, если что-то не так.

  3. Dashboard View - для создания дашборда с графиками и дополнительными таблицами результатов.

  4. Email Extension Plug-in - более удобная отправка email.

  5. Extra Columns Plug-in - возможность добавлять в таблицы дополнительные колонки.

  6. Git Client Plug-in и Git Plug-in - для поддержки git.

  7. Green Balls - озеленение удачных билдов, по умолчанию цвет синий.

  8. HTML Publisher Plug-in - публикация и ссылка на сформированный HTML репорт.

  9. inheritance Plug-in - создание однотипных задач с возможностью множественного изменения всех одновременно.

  10. Jenkins Violations Plug-in - статистический анализатор кода и отображение результатов.

  11. Violation Columns (List View Columns) - добавляет колонку в список по соответствующему плагину.

  12. Maven Project Plug-in - поддержка maven.

  13. Next-executions - добавляет панель со списком задач, которые скоро начнутся.

  14. Progress Bar Column Plug-in - показывает прогресс бар выполнения таблице билдов.

  15. Python Plug-in - запуск python скрипта в качестве шага.

  16. Warnings Plug-in - анализатор кода и визуализация результатов

  17. xUnit Plug-in - запуск и подключение результатов с возможностью задать условия для нестабильных и проблемных билдов.

Анализируй это…

Сам анализ в SonarQube, в нашем случае условно можно разделить на две части: первое – метрики по коду, второе – проблемы в коде (неверное использование функций, ошибки работы с памятью, неинициализированные переменные и т. д.).

Метрики нужны нам для анализа структуры кода, размеров функций, количества параметров, размеров файлов, содержимого функций (насколько там сложная логика и сколько ветвлений внутри).

Сейчас у нас существует пять основных требований к сложности кода:

1.     Размер функций

2.     Размер файла

3.     Сложность функций

4.     Количество параметров функции на входе

5.     Стиль кодирования (требования к оформлению кода)

У нас все построено вокруг pull-requests. Команда пишет код (фичу) до состояния готовности «замержить» его в основную ветку разработки или в релиз. Т. е. условно, мы готовы заливать готовый код в точку слияния всех изменений. Тогда создается pull-requests и вместе с ним в SonarQube стартует анализ кода, который предлагается к включению в ветку.

Платформа анализирует данные и определяет, удовлетворяет ли новый код принятым в данном проекте требованиям (пройден ли Quality Gate). При положительной оценке формируется отчет Success, при найденных багах и несоответствии заданным параметрам Failed.

Статус Success/Failed направляется назад в pull-requests и соответственно там может ставиться блокировка и ничего нельзя «замержить» по причине несоответствия кода заданным параметрам качества. Далее разработчикам нужно разбираться с причинами. При прохождении тестов SonarQube ничего не блокирует и вам остается лишь дать остальным процессам зеленый свет.

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

Грабли, подводные камни…

Вариант, при котором SonarQube спит, код идет, а функциональности здравствуют также реален, как и вариант, когда система ничего криминального не видит, но ничего не работает. А все потому, что система не проверяет логику происходящего. SonarQube всего лишь анализирует соответствие кода заданным параметрам. Глобально платформа не знает, какую фичу мы делаем, что код должен делать. Она всего лишь проверяет его соответствие правилам и доступность для понимания.

Анализатор не может глубоко залезть в логику, но первичные баги отследить вполне способен. Например, ошибки, связанные с неправильным использованием API. Тривиальные ошибки, когда используют переменную и только после этого проверяют, имеет ли она корректное значение. Например, пришел нулевой указатель, мы его вначале использовали, а только потом проверили. Такие вещи анализатор отлавливает и дает о себе знать.

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

К дополнительным плюсам SonarQube можно отнести и то, что платформа работает с более чем 20 различных языками программирования. Мы в основном работаем с С++, JavaScript, HTML, CSS, C#, Python.

Из минусов можно отметить то, что набор правил для SonarQube достаточно общий и не всегда подходит для каждого из наших проектов. Это требует внесения дополнительных индивидуальных настроек. Тюнинг – требует дополнительного времени. Не каждый готов его тратить.

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

Платформа находит проблемы, дальше воля владельца продукта, что-то с этим сделать или не делать, а талант разработчиков в том, чтобы, копаясь в «преданьях старины глубокой» ничего не поломать и не уронить.

Еще про страхи

Сгружать свой божественный код в черную коробочку – сомнительное удовольствие. Всегда есть риск отдать свои ноу-хау заморскому или отечественному «большому брату». Для здоровых снов и крепких нервов мы крутим все на наших серверах и в нашей базе данных. Дополнительно можно прикрыть тылы файрволом, чтобы анализатор не ходил, куда не нужно.  

Иногда утечки кода связаны с тем, что использовались дефолтные админские логины и пароли. В последних версиях SonarQube платформа настойчиво склоняет вас к сознательности, безопасной жизни и форсированной смене пароля администратора. (hint: если вы деплоите платформу автоматически и включаете SSO, не забудьте сходить админом и сменить пароль. Или же предусмотрите смену пароля при деплое.)

Год с Sonar

Позади 365 дней с SonarQube. В начале мы жили с ним в тестовом режиме. Платформа ничего не блокировала, работая в информационном режиме, высылая разработчикам отчеты с анализом кода.

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

Логика была такая: анализатор находит косяк, разработчик его исправляет. В начале бывало и такое, что несмотря на возмущения Sonar, команда двигалась дальше. Хорошая новость – ничего вопиющего не находилось (того, что прошло проверку и было «закомитчено»).

Бывали и такие ситуации, когда анализатор не находил существующие проблемы. Как в известном фильме: «Видишь суслика? И я не вижу, а он есть». Вообще стоит сказать, что статический анализ – это такая штука, где лучше использовать сразу несколько инструментов. Это существенно повышает шансы на безошибочную работу. Если есть возможность взять сразу несколько анализаторов – не отказывайте себе в удовольствии. Каждый из них точно что-то найдет. Так ваши нервы и код будут целее. У нас бывали случаи, когда используемые нами сторонние анализаторы ничего не находили, а штатный от Microsoft исправно сигналил.

Если вы спросите, кто больше всего у нас счастлив от наличия в компании SonarQube, ответ будет: «Примерно никто». Мы все-таки еще в процессе адаптации системы к жизненным процессам в нашей разработке.

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

Творческие планы

Постепенно мы расширяем возможности применения SonarQube. Задача – распространить анализ на максимальное число наших проектов. Цель – находить баги в самом начале, чтобы как у классика: «Не было мучительно больно за бесцельно прожитые годы». На самом деле главное требование к любому анализатору, он должен не мешать, а помогать разработчикам.

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

Бонус: полезная статья о том, что внедрять анализ кода надо на уровне компилятора или сборки.