Поднятая недавно тема парадокса «разбитых окон» привела к рождению данного поста. Как говорится, «чисто не там, где убирают, а там, где не сорят«. О важности чистого кода написана Робертом Мартином (Uncle Bob) замечательная книга Clean Code, которую я очень рекомендую почитать, а также посмотреть его видео-лекции на тему чистого кода: умно, кратко, понятно, по делу и с юмором.
Ну, а как же сделать так, чтобы команда в коде не сорила? Помимо устного свода правил, обучения новичков, проверки кода, есть некотоые инструменты, которые помогают каждому программисту в команде автоматически следить за качеством своего и чужого кода и замечать на ранних этапах следы «ржавчины», «разбитые окна» и мусор в коде, еще до того, как наросли сверху слои нового мусора и ржавчины. Чем раньше и быстрее вы будете убирать мусор, тем явнее будет виден новый мусор, тем труднее будет в чистом коде сорить вам и другим разработчикам в команде.
Исходные условия
В поддержании чистоты нашего кода нам поможет следующий набор инструментов:
- IDE — Eclipse. Это мое предпочтение. У каждого программиста оно свое. Главное, проект не должен содержать файлов и настроек, специфичных для какого-то конкретного IDE. Проект должен быть, как говорится, «IDE-нейтральным», т.е. его можно извлечь из репозитария, собрать и запустить вообще без всякого IDE — из командной строки;
- управление зависимостями: Maven или Gradle. Maven очень удобен для простых проектов. Gradle сейчас набирает в популярности, хотя, честно говоря, с каждой новой версией он становится все жирнее, неповоротливее и запутаннее;
- управление кодом: SVN / Git. SVN теряет в популярности, Git его превосходит по всем статьям. Если у вас большой проект и много разработчиков в команде, выбирайте только Git, чтобы потом не заморачиваться с болью при переносе проекта из SVN в Git;
- управление задачами: JIRA
- управление ветками кода: BitBucket. Прекрасно интегрируется с JIRA
- управление сборками: Jenkins / TeamCity. TeamCity мне нравится больше, но он платный. Jenkins по многим праметрам убог, но он — бесплатен;
- управление документацией: Confluence или MediaWiki
[ См. также: Как стать хорошим программистом и им оставаться ]
Настройка IDE
Включаем все предупрежения Java-компилятора в Eclipse. Именно ВСЕ! Все до единого. Если Eclipse показывает предупреждения, код не коммитится. Если вы обновили свою локальную копию из репозитория и увидели, что свежий код содержит предупреждения компилятора, значит кто-то в вашей команде настолько ленив, что не соблюдает правила чистого кода. История коммитов вам скажет, кто это.
У Eclipse-а свой собственный встроенный Java-компилятор, поэтому, если в команде кто-то использует другой IDE, он может не видеть многих ошибок, которые показывает Eclipse.
Eclipse показывает не только предупреждения, но и потенциальные ошибки: потенциальные NullPointerExceptions, dead code, присвоение вместо сравнения и даёт прочие полезные замечания по качеству кода.
Плагины для Eclipse
Дополним Eclipse следующими полезными плагинами:
- плагин SpotBugs — статический анализ кода. Позволяет найти как грубые ошибки, так и ошибки потенциальные. Раньше был плагин FindBugs, разработчик его потом забросил, другие разработчики форкнули проект и продолжили его развитие уже под названием SpotBugs
- плагин Eclemma — проверка покрытия кода тестами
Дополним Maven / Gradle
С помощью плагина Spotless в Gradle/Maven проводится проверка кода на следование правилам форматирования. Eclipse позволяет создать определенные правила форматирования кода и экспортировать их в xml-файл. Этот файл можно поместить в репозиторий вместе с проектом, и каждый член команды, подготавливая свою среду разработки, может импортировать этот файл в свой Eclipse, и таким образом обеспечивается у всех одинаковое форматирование кода. Spotless плагин умеет прочитать этот файл и применить правила форматирования к коду, либо проверить код на соответствие этим правилам. Таким образом, перед коммитом каждый разработчик проверяет еще и форматирование кода.
ВНИМАНИЕ: Здесь кроется неприятный косяк. Практика показала, что разные версии Eclipse читают файл форматирования по-разному и применяют правила форматирования так, как считают нужным. Получается в Eclipse код отформатирован, а spotless плагин кричит, что форматирование нарушено. В результате у вас возникают конфликты, если разные разработчики пользуются разными версиями Eclipse, либо вы все вынуждены пользоваться определенной версией Eclipse и не можете его обновить до новой версии.
Билд одной командой
Инфрастурктура проекта должно позволять скомпилировать и собрать его из командной строки без всякого Eclipse.
Юнит тесты
Юнит-тесты с помощью JUnit. Думаю, мне не стоит объяснять, насколько это важно.
Плагин Eclemma для Eclipse позволяет отследить покрытие кода тестами.
Непрерывные билды и непрерывная интеграция
Jenkins и постоянные автоматические тесты (CI — continuous integration) на ветке перед тем, как ветка подается на код-ревью.
В Jenkins устанавливается несколько плагинов, которые проверяют код во время каждого билда:
- проверка стиля плагином Spotless,
- проверка количества предупреждений (warnings),
- проверка SpotBugs-ом на баги,
- плагин Eclemma, который выводит красивый график покрытия тестами по каждому классу вашего проекта и показывает всей команде, какие участки кода еще не затронуты юнит-тестами.
Ветки кода и ревью кода
Следуя правилу Gitflow, разработка ведется на ветках. Каждая фича, багфикс сначала описывается в JIRA, потом создается ветка под эту JIRA, новый код коммитится в эту ветку, создается Pull request, Jenkins подхватывает этот pull request и делает билд со всеми проверками. Если билд удачно проходит все тесты, pull request подается на ревью. Ревью начинается только тогда, когда:
- билд закончен
- билд закончен успешно
Код-ревью делает несколько человек. Несколько человек должны одобрить код, прежде чем он может быть добавлен в главную ветку. Одного одобрения — недостаточно. После получения двух одобрений, код из ветки вливается в главую ветку. Это вливание тоже подхватывается Jenkins-ом и тоже проходит все проверки.
Основная ветка
Если сборка главной ветки в Jenkins ломается из-за нового вливания, виновник поломки бросает все и чинит сборку. Отмазка «на моей машине все работает» и «мой билд в ветке был зелёным» не принимается.
Код в главной векте всегда должен быть зелёным. Это значит его можно в любой момент извлечь из репозитория, скомпилировать, собрать и выложить на PRODUCTION, и он будет работать.
Итог
Это как бы несколько линий защиты, каждая из которых отсеивает глупейшие и очевидные ошибки, и все вместе позволяют вычистить код от мусора, удержать за руку «торопыг» и «абыкакеров».
А с чистым кодом легче уже работать над реальными ошибками архитектуры, кода или дизайна.