В данной статье мы поговорим о важности написания качественного кода. Многие ошибочно считают, что код, создаваемый автоматизаторами, не должен проходить процесс ревью. Мол, это ведь не продакшен код, зачем его ревьювить? На это могу сразу задать встречный вопрос: а какая разница, продакшен он или нет?
Так или иначе, мы в какой-то степени программисты. Мы создаем фреймворки, моделируем доменный абстрактный слой, пишем тесты на выбранном языке программирования. Так с чего бы вдруг мы должны игнорировать документированные правила языка? Разве мы не обязаны стремиться к написанию гибкого, хорошо поддерживаемого кода, который был бы всем интуитивно понятен, реюзабелен для других проектов?
Если копнуть глубже и провести поверхностный root cause analysis, то причиной данного распространенного заблуждения могут служить: либо синдром бога, мол - я пишу код, и он весь такой классный, в нем не может быть ошибок по определению; либо боязнь быть раскритикованным, мол - я новичок, еще многого не знаю, а тут меня сейчас какахами закидают, появятся комплексы и я вообще брошу автоматизировать.
Тут следует усвоить 2 правила:
- Не бывает идеального кода. Баги можно найти везде. Посему нужно привлекать независимых экспертов, которые смогут более трезво оценить ваш код.
- Код ревью направлен прежде всего на улучшение качества кода, а не на унижение реквестера. Не стоит воспринимать комментарии на свой личный счет. Все мы учимся. И это - один из способов саморазвития.
Итак, хватит лирики. Дальше мы поговорим о том, как проводить анализ своего кода до того, как отправлять его на ревью, создавая pull requests. Такой себе pre-commit analysis.
Применительно к Java, мы можем воспользоваться инструментом под названием SonarQube, представляющим из себя open source платформу для осуществления контроля качества кода.
В двух словах, процесс выглядит следующим образом: запускается анализатор кода (к примеру, посредством sonar maven plugin), покрывающий следующие code quality оси:
Результаты отправляются Sonar серверу, где вы сможете ознакомиться с найденными проблемами и подсказками к их решению.
Рассмотрим сей продукт на реальном примере из нашей базы знаний. Специально взял свой собственный код, чтобы показать, что:
- я тоже человек и допускаю ошибки;
- я не боюсь процесса код ревью.
Другой вопрос: как код с ошибками попал в мастер репозиторий? Естественно, речь идет не об ошибках компиляции. Но, да, да, я - редиска, создал PR без предварительного Sonar анализа. В оправдание ревьюверов могу только сказать, что некоторые из рассмотренных ниже ошибок не так легко распознать.
Итак, приступим к анализу моего кода.
- Первым делом необходимо установить SonarQube 4.5.1 (LTS) (на момент чтения версия может быть другой). Скачиваем архив.
- Распаковываем в любое удобное место.
- Шагаем в bin folder.
- Открываем директорию, соответствующую вашей системе.
- Запускаем Start Sonar.bat (WIN).
В результате должно появиться нечто вроде этого:
Проверяем, что сервер запущен. Вбиваем в браузер localhost:9000
(дефолтный адрес) и видим следующее:
Предположим, что исходники проекта вы уже выкачали. Теперь создадим 2 maven run configuration:
Для корректного анализа Sonar требует предварительного запуска install goal, иначе получите кучу class loader ворнингов. Детальнее сможете прочесть в официальной документации.
В процессе исполнения sonar:sonar goal, плагин проверит, запущен ли сервер на дефолтном хосте (можно задать кастомный адрес). В случае успеха, ваш код будет жестко разобран и раскритикован, а результаты смогут наблюдать все, у кого есть доступ к вашему серверу.
Конечно в идеале сервер должен быть поднят на каком-то независимом окружении, к которому будут иметь доступ все члены команды. Но это уже out of scope.
Итак, представим, что мы все сделали верно, тогда в консоли можно будет наблюдать следующее:
Шагаем на дешбоард нашего сервера и находим наш проект:
Воу-воу-воу, сразу бросается в глаза technical debt - 1h 44min. Значит не все так идеально, как казалось, не так ли? За нас уже и посчитали приблизительное время на фикс найденных ошибок.
Раскрыв детали, можно увидеть множество полезной статистики. Но внимание следует все же уделить выделенным блокам:
Sonar уже распределил найденные ошибки по важности. Major severity по идее должно нас сильно испугать, посему за фикс именно этих багов мы первым делом и беремся.
Раскрыть подробную статистику ошибок можно либо посредством клика по соответствующей линке (кол-во), либо путем выбора меню Issues Drilldown.
Данный пейдж является основным для разбора полетов. Помимо severity, сразу бросается в глаза группировка по правилам (по сути саммари ошибок), клик по которым дает нам возможность увидеть список классов, в которых данная ошибка присутствует. Раскрыв сам класс, можно увидеть более точную информацию по проблемному месту.
Итак, идем по порядку:
Скобочки, как мы знаем, должны идти в соответствии с правилами языка. Даже если тело пустое. К счастью, в IntelliJ IDEA это решается путем вызова code reformat диалога: CTRL + ALT + L, Enter и вуаля - 2 бага пофикшено!
Возвращаясь к деталям, видим во-первых, что прогнозируемое время фикса (Debt: 1min) - более или менее точноe. Во-вторых, подсказки к решению настолько очевидны, что вам даже не надо ничего гуглить, чтобы решить данную проблему. Конечно далеко не всегда решения будут столь тривиальны, но согласитесь, что на таких вещах можно легко учиться!
Стоит отметить, что правила, которые используются для анализа вашего кода, могут кастомизироваться. К примеру, у нас в организации есть свои code style шаблоны. Sonar не обойдет стороной ваши policy. Вам необходимо лишь загрузить нужные темплейты.
Поехали дальше.
В Email классе мы видим целых 4 ошибки, связанные с несоблюдением java name convention - created_at филд с сопутствующими геттером / сеттером - явно не пример для подражания. Но как же быть? Ведь поле json’а, возвращающего структуру письма, содержит именно такое имя. Если мы его изменим, филд попросту не будет найден. Но выход есть! Путем явного задания аннотации @JsonProperty
, мы сможем и парсер удовлетворить, и правила соблюсти.
Следующие 2 ошибки говорят о том, что если мы ловим эксепшены, то хорошо бы их логгировать или выплевывать наружу:
Не беда! Добавляем логгирование.
Далее немного сложнее:
Количество условных операторов, используемых в 1 выражении, велико. Решаем путем декомпозиции:
Но здесь же еще одна ошибка:
Тут нам советуют использовать готовые API проверки коллекции на пустоту. Оптимизируем обе строки с учетом декопмозиции:
Последний баг у нас относится к дублированию строк:
Выносим в константу и правим вхождения:
Ну что, пожалуй пора перезапустить анализатор и посмотреть результаты.
О чудо, technical debt = 0. И пусть теперь только попробуют придраться к моему PR.
В заключении отмечу, что Sonar - не панацея от всего. Доменных ошибок, связанных с логикой работы ваших тестов, этот инструмент конечно же не выявит. Но confidence в качестве вашего кода стремительно возрастет как у вас, так и ваших коллег / ревьюверов.
Wish you code quality improvement and Happy New Year!