Добрый день, %username%

Хочу поделиться своим успешным опытом внедрения автоматической проверки стилей кода в проект и рассказать на какие грабли наступали. Опубликовать opensource сообществу инструменты, которые были созданы для решения задачи

Немного о нашем проекте: PHP сайт, лежит в git репозитории объемом 2Gb, состоит из 20k php файлов, возраст проекта- 10 лет, в данный момент у нас 15 разработчиков. Для code review используем atlassian stash. Всю разработку ведем в рамках отдельных веток, которые после прохождения code review вливаем в master и деплоим на прод

Для начала вопрос: а зачем? Зачем вообще следить за стилями кода?
Ответ для меня простой: код пишется один раз, а читается потом десятками людей на протяжении многих лет. Следовательно стоимость поддержки кода многократно превышает стоимость написания. А раз так — то стоит потратить немного времени и отформатировать код согласно некому стандарту

Первое на что наткнулись: а какой стандарт выбрать? Поступили так — создали свой стандарт, унаследованный от symfony, и вносим туда изменения согласно нашему представлению о прекрасном. Некоторые правила мы просто выбрасывали, как невозможные в нашем проекте для старых классов (например, то что любой класс должен быть внутри namespace). Благо phpcs представляет хорошие возможности по настройке стилей кода

Второе: а чем проверять код? Какие есть утилиты для этого? После недолгих поисков остановились на phpcs, так как есть нативная поддержка в phpstorm

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

Третье: а как собственно проверять код?
Тут были разные варианты
  • Как известно, git поддерживает серверные хуки. Можно проверять стили на стороне сервера и не давать запушить, пока ошибки не будут исправлены. Но такой подход мне не понравился, так как бодаться пушами с гитом в консоли не очень-то удобно :) Плюс тут невозможно сделать обходной путь, когда исправить все ошибки в стилях по каким-то причинам невозможно (например, нужно переименовать имя метода, который используется в 100500 файлах)
  • После некоторых размышлений решили, что идеальный вариант, когда робот будет сам отписываться в pull request про найденные ошибки в стилях, которые уже разработчик должен будет исправлять. При этом на первом этапе мы разрешали какие-то ошибки не исправлять, если это требовало существенно рефакторинга, дорабатывали удобные для нас правила проверки. Так родился инструмент — phpcs-stash


Немного об архитектуре инструмента:
1) При пуше в некоторую ветку webhook дергает phpcs-stash и передает название ветки, куда был сделан push
2) phpcs-stash запрашивает по API у stash все рецензии (pull requests) с этой веткой, проходится по всем файлам (дергает их так же из stash по API), проверяет стили, отписывается где нашел ошибку. В случае если ошибок нет — аппрувит рецензию. Отписывается робот только в измененных строках
Результат выглядит вот так:

3) При повторном пуше робот заново проверяет все рецензии, удаляет комментарии об исправленных ошибках

Для любителей картинок:


При таком подходе у нас остается возможность настройки родной интеграции между stash и jira (например: запретить закрывать задачу если рецензия кода не одобрена роботом). И есть отличная возможность анализировать какие ошибки случаются чаще всего, что бы дорабатывать правила проверки

Так как система проверки не знает ни о чем кроме atlassian stash, было решено сделать её ориентированной в open source. Изначально делалось только для PHP, но парням из соседнего отдела понравилось и они сделали поддержку проверки C++ кода

Для быстрой обратной связи используется phpstorm, который умеет интегрироваться с phpcs. Выглядит вот так:


Что дальше?

Есть идея сделать проверяльщик интерактивным: чтобы можно было ответить на комментарий робота «исправь», и робот бы сам исправил ошибку, если её можно исправить (например, отсутствующий пробел). Но, к сожалению, я не нашел инструментов, которые могут исправлять стили в конкретной строке. Если сообщество подскажет — буду рад

Ссылки:
Поделиться с друзьями
-->

Комментарии (31)


  1. heilage
    28.06.2016 06:27
    +1

    1) А чем пре-коммит хуки не понравились? Или у вас в проекте настолько легаси, что файлы по 4000+ строк?
    2) Не задумывались над тем, чтобы прогнать автоматическое переформатирование кода на всем проекте? Один раз и навсегда.


    1. Ents
      28.06.2016 08:09

      1) Пользоваться не так удобно как с web интерфейсе. Хук можно отключить и забыть об этом. В качестве быстрой проверки используются стандартный проверщик phpstorm (там тоже phpcs под капотом)
      2) Задумывались, но отказались, так как ка хотели терять авторов последних строк


    1. LionAlex
      28.06.2016 09:19

      1) Проблемы теже, что и с pre-recieve, да еще и у всех настраивать надо
      2) А кто потом это вычитывать будет и смотреть, что ничего не сломалось?


      1. flr
        28.06.2016 11:47

        А какие проблемы есть с pre-receive?


        1. Ents
          28.06.2016 11:50

          Во-первых — удобство (читать diff с подсветкой удобнее, чем просто список строк с ошибками в консоли)
          Во-вторых — рубится на корню всякая возможность проигнорировать предупреждения проверщика стилей (а это бывает необходимо, когда исправление стилей требует исправления сотен классов, скажем, для переименовывания метода, который много где переопределяется)

          А в данном случае все ошибки на этапе code review видны всем разработчикам, и они прям в комментариях могут договориться что какая-то ошибка не может быть исправлена и проигнорировать её


      1. heilage
        28.06.2016 11:50

        1) Кажется, что в среднем пре-пуш (или интеграция проверок на ide) дает более быструю обратную связь разработчику. Можно использовать в совокупности с пре-ресив хуками, конечно.
        2) Автоматическое переформатирование должно гарантировать корректность кода. Если оно не может гарантировать корректность в каких-то специфических случаях — оно не должно трогать код и должно требовать от разработчика правильным образом его исправить.

        Вот с частичной потерей истории в git — это да, существенный момент. Однако по себе могу сказать, не так уж оно и нужно — в один прекрасный момент поймал себя на мысли, что лезу в blame чисто посмотреть, кто такую херню написал :) Зачем, почему, как исправить — как правило понятно из кода (а если непонятно, то есть комментарии). Так или иначе, в пушистом легаси коде отсутствие комментариев и неявность намерений исходного автора может действительно быть существенной причиной не делать авто-преобразований.


        1. Ents
          28.06.2016 13:30

          Для быстрой обратной связи существует phpstorm, где прямо в момент написания кода подсвечиваются ошибки
          image


    1. OnYourLips
      28.06.2016 23:14
      +1

      > А чем пре-коммит хуки не понравились?

      Потому что они работают на машине разработчика, где ОС и окружение рандомные, а PHP и вовсе может не стоять (у меня нет PHP на рабочей машине, только в виртуалках для проектов, причем для разных проектов — разные версии, разные настройки и т.д.).
      А код выполняется на личной виртуалке разработчика с приближенным к продакшену окружением.
      Поэтому хук должен стоять на стороне сервера, а не клиента.


      1. heilage
        29.06.2016 06:06

        Они работают там, откуда вы коммитите код. Ничто не мешает коммитить с личной разработческой виртуалки, где есть всё, что нужно.


        1. OnYourLips
          29.06.2016 09:00
          +1

          Виртуалка — это часть проекта. Репозиторий же находится на рабочей машине, где находятся все рабочие инструменты, включая IDE и git.
          И запускать рабочие инструменты внутри виртуалки — это какое-то извращение.


        1. Ents
          29.06.2016 10:01

          главная ценность — простота и удобство пользования
          Поддержка 15 виртуалок разработчиками (по одной виртуалке на каждого разработчика) — это существенная дополнительная работа, которая исключается в случае наличия централизованного инструмента


          1. xotey83
            29.06.2016 13:40

            Если у вас есть инструмент поддержики конфигурации а-ля puppet, то проблемы нет.


            1. Sannis
              05.07.2016 22:28
              +1

              Вы разрешите доступ к своему ноутбуку и виртуалке на нём админскому паппету? Думаю нет :-)


              1. xotey83
                08.07.2016 16:31

                Не к своему ноутбуку, а к виртуалке, на которой подняты все сервисы для разработки: php-fpm, nginx, mysql (для экспериментов), xdebug, туда же приностися конфигурация приложения (мы используем подобие etcd), и прочее. Вот эта виртуалка и управляется папетом.
                А ноутбук используется в качестве тонкого клиента: phpstorm, браузер и ssh-клиент.

                UPD. Уточню: виртуалка находится не на ноутбуке, а на девелоперском сервере.


  1. Borro
    28.06.2016 08:00

    Еще можно добавить к валидации https://phpmd.org/ — помогает писать более чистый код. Правда я бы подкрутил его настройки, например CyclomaticComplexity, NPathComplexity.


    1. Ents
      28.06.2016 08:10

      Да, это есть в планах. Когда буду делать — оформлю в виде отдельной утилиты, по аналогии с phpcs-stash


  1. maximkou
    28.06.2016 08:04

    В readme.MD у вас опечатка — brach вместо branch.

    И еще немного провоцирующий вопрос: а какой стандарт стиля установлен в самом инструменте? (просто по коду местами используются разные стили написания). Чтобы не быть голословным: везде отступы пробелами, а например здесь — табами.


    1. Ents
      28.06.2016 08:14

      спасибо, опечатку и ошибку в стиле исправил
      Как такой стиль кода не задан, но я по привычке пишу в symfony code style http://symfony.com/doc/current/contributing/code/standards.html


      1. maximkou
        28.06.2016 08:20
        +4

        Исправьте уж везде тогда) А не только там где я указал)

        Как такой стиль кода не задан

        Это конечно сугубо мое личное мнение, но раз уж инструмент следит за код-стайлом, он сам должен не иметь вопросов по тому самому код-стайлу.

        Вы же не будете пользоваться, например инструментом тестирования, если он сам не оттестирован?


  1. andrewnester
    28.06.2016 08:46
    +1

    У нас похожая ситуация с проверкой кода. На каждый пулл риквест запускается задача на CI сервере на проверку стиля. Если есть нарушения, пулл риквест будет иметь статус failed и бот отпишет где и в каких местах проблемы.
    Плюс написан свой линтер, который у разработчиков вызывается локально на pre-commit hook
    Всё круто работает, иногда правда с легаси кодом проблемы бывают


    1. Ents
      28.06.2016 09:11

      А проверяется только измененный код в рамках данной задачи, или весь проект целиком?


      1. andrewnester
        28.06.2016 13:47

        только изменённый, на CI есть задачи проверки и всего кода


  1. LionAlex
    28.06.2016 09:22

    Есть идея сделать проверяльщик интерактивным: чтобы можно было ответить на комментарий робота «исправь», и робот бы сам исправил ошибку

    А не боитесь, что он там вам накоммитит не того?

    Какой-то странный у вас кодстайл :)
    https://github.com/WhoTrades/phpcs-stash/blob/master/lib/Checker/PhpCs.php#L11

    class PhpCs implements CheckerInterface
    {
    	 /**
         * @var \PHP_CodeSniffer
         */
    	private $phpcs;
    	/**
         * @var Logger
         */
    	private $log;
        /**
    	 * @param Logger   $log
         * @param array $phpcs - ['encoding' => '....', 'standard' => '...']
         */
    	public function __construct(Logger $log, array $config)
    	{
    


    Ой
    var_export($core->runSync('refs/heads/feature/WTA-623', 'WT', 'sparta'));
    


    1. Ents
      28.06.2016 11:28

      Да, часть кода писалась в nodepad++, а там ставится таб, а не пробел. Потому вперемешку. Исправил

      По поводу var_export() — app.php это пример использования библиотеке, для самой простой интеграции — webhook. У нас в живом проекте phpcs-stash подключается с помощью composer и работает внутри очереди


      1. minamoto
        04.07.2016 14:07

        Там есть опция специальная, позволяющая сразу при написании заменить таб необходимым количеством пробелов. Очень удобно, рекомендую.


  1. LionAlex
    28.06.2016 09:38

    Зачем дергать напрямую $GLOBALS['PHP_CODESNIFFER_CONFIG_DATA'], если есть PHP_CodeSniffer::setConfigData( string $key, string|null $value, [boolean $temp = false])?


    У вас в код-стайле нет ограничения длинны метода? Кажется, RequestProcessor::processRequest излишне жирный и слишком много на себя берет.


    А как-же юнит-тесты? :)


    А вообще, спасибо, инструмент интересный и полезный в вашем случае. К счастью, у нас можно пофашиствовать и использовать хуки.


    1. LionAlex
      28.06.2016 09:48

      Ну и в дополнение – в настройках PHPStorm можно указать путь до рулсета phpcs и он будет подсвечивать ошибки стиля еще на этапе написания кода.


      1. Ents
        28.06.2016 11:25

        Мы это используем, но опять таки, phpstorm не гарантирует отсутствия ошибок в стилях (писал в комментах выше)


  1. TheRat
    28.06.2016 11:29
    +3

    Рекомендую посмотреть github.com/phpro/grumphp


  1. GliX
    28.06.2016 17:38
    +1

    https://styleci.io/ — вот такое еще есть.


  1. Sannis
    05.07.2016 22:30

    Попробуйте phpcf — он умеет как находить, так и исправлять ошибки форматирования. Кроме того, если его запускать из git репозитория, он может проверять только те строки, которые были изменены с последнего коммита.