Автоматизированная проверка PHP кода при комитах

    В свое время работая в узком кругу программистов, отдельными задачами и даже проектам, мы не задумывались о проблемах связанными с текучкой кадров. Точнее думать — думали, но ни каких мер не применяли, да и в целом коллектив был сплоченный никто не уходил и никого «не уходили». С ростом внутренних проектов и корпоративных клиентов, штат начал разрастаться и казалось, что все отлично — нас больше, значит будем больше успевать и делать, но не тут то было. Мы начали тратить кучу времени на “бесполезные” обсуждения, проверки, излишние проектирование и т.д, больше всего раздражает — это проверка кода. И тут я начал думать, что “мудрые и древние” наверняка решали эти проблемы с сотнями, тысячами программистов, неужели мы не справимся? Я решил провести эксперимент, под названием “автоматизированная проверка стиля кода при комитах”. Для большинства из Вас это не новость и наверняка вы этим пользуетесь, но поделиться опытом внедрения думаю, не будет лишним.

    Воскресения, 3:40

    В это ранние время, сидя за работой и сделав перерыв на чай, я задумался, завтра нужно ехать в офис и снова утром тратить 2 — 3 часа на проверку кода, потом еще 2 часа на постановку задач, итого 5 часов, потом может быть поработать 2 часа и ехать домой. И понятное дело, что задачи которые поставили, я не могу решить за оставшиеся 2 — 3 часа, а решая эти проблемы в неурочное время могу разрушить свою семью и т.д. Так дальше не может продолжаться. В первую очередь я программер, а не «цербер» и нужно автоматизировать процесс проверки, это если не снимет все время проверки, то хотя бы сократит.
    Не люблю изобретать колесо, потому сразу обратился к поисковику и задал запрос: «checking coding standards PHP», просматривая первый десяток результатов обратил внимание на часто встречающийся название "PHP_Codesniffer" и задав одноименный запрос — увидел, что это PEAR библиотека для автоматизированной проверки стиля кода, как говориться -«то что, доктор прописал!» и надежности разработчиков сомневаться не приходиться, что благотворно повлияет при возможном глобальном внедрении. Установив на сервер библиотеку:

    pear install PHP_CodeSniffer-1.3.0RC1

    Предполагаться, что у вас установлен дистрибутив PEAR на сервере. После установки станет доступна новая служба phpcs:

    phpcs --standard=Zend your.php

    Не много поигравшись, меня порадовало, что уже данное решение поддерживает многие стандарты: Squiz, MySource, PHPCS, Zend, PEAR. Меня это устраивало, так как мы утвердили в свое время, что будем кодить согласно стандарту Zend.
    Про затачивания это библиотеки можно почитать в официально документации

    Воскресение, 4:00

    Окрыленный своей находкой и быстрым ее “поднятием”, сон отступил. Первая задача была решена, теперь осталось подключить это решения к контролю версий при комите. В документации к PHP_CodeSniffer есть раздел посвященный описанию интеграции с SVN — это было хорошо, так как у нас SVN любят использовать, но я использую GIT и решил писать свой хук для git и тут думаю: “не верю, что на PEARовское решения нет описания интеграции c GIT”. И снова обратившись к поисковику нашел готовое решение phpcs-pre-commit:

    git clone https://github.com/s0enke/git-hooks.git

    Для интеграции этого хука нужно положить файлик pre-commit в папку hooks вашего git репозитория (.git/hooks). Кто интересовался git хуками — тот в теме.
    И последние проверка коммита мне вывелась таблица с описание ошибок не соблюдения стиля. Не буду приводить пример того, как отображает таблицу ошибок phpcs, да и зачем. В .git/hooks/pre-commit нужно указать какой стиль вы хотите использовать:

    PHPCS_CODING_STANDARD=Zend

    Также укажите расширения файлов которые необходимо проверять:

    PHPCS_FILE_PATTERN="\.(php|phtml)$"

    Если при комите вам выдает ошибку:
    error: cannot run .git/hooks/pre-commit: No such file or directory
    Это значит, что указан не правильный путь к bash, измените его в .git/hooks/pre-commit

    Задача в целом решена, плюс CodeSniffer в том, что с ним обязанность проверять “юношеские” ошибки, которые свойственны всем — отпадает. И главный плюс, что заставит “молодых” просматривать код как минимум при поиски ошибки стиля и возможно проведения минимального рефакторинга.
    Теперь можно в понедельник ехать на работу и рассказать об нововведениях. Если это поможет нам, то можно будет идти лоббировать интеграцию данного решения для всех.

    Понедельник, 17:00

    В целом все было отлично, но проект на котором решил тестировать, довольно таки древний и некоторые моменты привести к стандарту Zend было накладно, например верблюжий стиль переменных. И пришлось создать свой стандарт для PHP_Codesniffer. Сами описания проверки стиля лежат в:

    PEAR_PATH/PHP/CodeSniffer/Standards/

    PEAR_PATH — это путь к папке с PEAR библиотеками у нас на сервере они располагаются в /usr/local/share/pear/.

    Для создания своего стиля создайте папку YOUR_STYLE в PEAR_PATH/PHP/CodeSniffer/Standards/.

    В паке вашего стиля нужно создать ruleset.xml. Про формат этого файла можно почитать тут, опишу только-то, что пригодилось мне.
    Связи с тем, что требования кодированию максимально приближены к Zend стилю, просто скопировал содержание с PEAR_PATH/PHP/CodeSniffer/Standards/Zend/ruleset.xml:
    <?xml version="1.0"?>
    <ruleset name="Zend">
    <description>A coding standard based on an early Zend Framework coding standard. Note that this standard is out of date.</description>

    <!-- Include some sniffs from all around the place -->
    <rule ref="Generic.Functions.FunctionCallArgumentSpacing"/>
    <rule ref="Generic.Functions.OpeningFunctionBraceBsdAllman"/>
    <rule ref="Generic.PHP.DisallowShortOpenTag"/>
    <rule ref="Generic.WhiteSpace.DisallowTabIndent"/>
    <rule ref="PEAR.Classes.ClassDeclaration"/>
    <rule ref="PEAR.ControlStructures.ControlSignature"/>
    <rule ref="PEAR.Functions.FunctionCallSignature"/>
    <rule ref="PEAR.Functions.ValidDefaultValue"/>
    <rule ref="PEAR.WhiteSpace.ScopeClosingBrace"/>
    <rule ref="Squiz.Functions.GlobalFunction"/>

    <!-- Lines can be 80 chars long, show errors at 120 chars -->
    <rule ref="Generic.Files.LineLength">
    <properties>
     <property name="lineLimit" value="120"/>
     <property name="absoluteLineLimit" value="140"/>
    </properties>
    </rule>

    <!-- Use Unix newlines -->
    <rule ref="Generic.Files.LineEndings">
    <properties>
     <property name="eolChar" value="\n"/>
    </properties>
    </rule>
    </ruleset>


    В теге ruleset замените имя на свое имя YOUR_STYLE и добавляю одно правило с Zend:

    <rule ref="Zend.Debug.CodeAnalyzer"/>

    Для отключения верблюжьего стиля копирую:
    PEAR_PATH/PHP/CodeSniffer/Standards/Zend/Sniffs/NamingConventions/ValidVariableNameSniff.php в PEAR_PATH/PHP/CodeSniffer/Standards/YOUR_STYLE/Sniffs/NamingConventions/ValidVariableNameSniff.php. Переименовав класс с Zend_Sniffs_NamingConventions_ValidVariableNameSniff на YOUR_STYLE_Sniffs_NamingConventions_ValidVariableNameSniff, добавил:

    public $isCheckCamelCaps;

    И добавил везде проверку на этот “флажок”. Теперь если нужно будет его переопределить — это можно будет сделать из ruleset.xml:
    <rule ref="YOUR_STYLE.NamingConventions.ValidVariableName">
    <properties>
     <property name="isCheckCamelCaps" value="1"/>
    </properties>
    </rule>


    Вторник, 19:00

    Повсплывало много моментов на которые свое время закрывались глаза, но пришло время их приводить в порядок! Самой полезной проверкой стиля кода оказалась проверка на длину строки кода, и благодаря ее было зарефакторено много нечитабельных мест.
    Правда столкнулись с проблемой с русскими комментариями, код весь хранится в UTF-8, а CodeSniffer длину строки проверяет стандартным strlen и логично что строки увеличивались в два раза. Не стал я заморачиваться на переопределения класса, что было бы правильнее, а просто в PEAR_PATH/PHP/CodeSniffer/Standards/Generic/Sniffs/Files/LineLengthSniff.php добавил:

    public $charset = 'UTF-8';

    и заменил strlen, на:

    mb_strlen($lineContent, $this->charset)

    Суббота

    Прошла нелегкая неделя с CodeSniffer, и вот какие плюсы:
    • Снимается время и нервы на проверку стиля кода;
    • при исправление ошибок длины строк, пересматриваешь логику кода, что благотворно влияет на читабельность кода и проведения рефакторинга мутной логики. Также снимается надобность объяснять когда одно-строчные if хорошо, а когда плохо;
    • снимается обязанность следить за документацией стиля кодирования;
    • поддерживает проверку всех популярных стандартов кодинга.

    Минусы:
    • Неудобно внедрять в “исторические” проекты или чужие, можно потратить несколько дней, а то и недель на наведения икебаны;
    • не удобно внедрять с контроль версиями, так как без напильника не подымешь, что для GIT, что для SVN. Особенно когда проектов несколько десятков и не для всех одинаковый стиль кодинга.
    Share post
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 48

      0
      Мы используем pre-update на мастере вместо pre-commit у каждого разработчика.
      Стиль форматирования и прочие плюшки вида skipsniff задаётся через git config.
        +7
        И поправьте название — не проверка кода, а проверка стиля форматирования кода.
          0
          Жаль, что автор вас не слышит.

          Автору: Таки поправьте наконец! В заголовке необходимо указать, что речь идёт только о форматировании кода, а не проверке вообще. Сейчас заголовок вводит в заблуждение.
        +1
        Не знаю — на меркуриал ставится все на ура, после траты 20 минут на ман.
          0
          1. А на какой обработчкик вы его к HG прикрутили?
          2. Каждому раз работчику или в интеграционный репозиторий (да я понимаю, что у вас может быть другой workflow)?
            0
            1. pretxncommit
            2. каждому
            0
            Да с меркуриалом всё так. 20 минут манов/вики — и заработало. Безобразие.
            0
            Всё хорошо и правильные, но русские комментарии — моветон.
            • UFO just landed and posted this here
              • UFO just landed and posted this here
                  +1
                  Если честно, я поражен вашим вопросом. Вы же не пишете код на русском?
                    +9
                    Но и на английском я его не пишу. Я его пишу на языке программирования.
                      0
                      Но программист из любой другой страны ваш код поймет, а комментарии — никогда.
                      • UFO just landed and posted this here
                          0
                          По этому поводу чуть выше заметили — если ваша система для внутреннего использования, то не имеет значения (я сам всегда на английском пишу комментарии если что)
                      +4
                      Потому что вы ограничиваете множество людей, которые будут читать ваш код до русскоговорящих. Разве не очевидно?
                      • UFO just landed and posted this here
                          0
                          Это просто стиль кодирования, стандарт. В конце концов в русском языке как правило нет подходящей IT-терминологии, названия методов и переменных тоже на английском, в итоге вы получаете полную кашу.
                          Любой специалист прочтет ваш комментарий, если нет — то он отвратительный специалист и не место ему в сфере.

                          Вы завтра пойдете устраиваться на работу в иностранную компанию, и покажете свой лучший исходник, а там бац, и комментарии на русском языке.
                          • UFO just landed and posted this here
                              +1
                              Стили и стандарты кодирования регламентируются, как правило, внутренними договоренностями команды. Если команда не планирует расширяться за счёт нерусскоговорящих, то комментарии на русском вполне допустимы, имхо, а если команда ещё и английским владеет не свободно (как я пишу в резюме «читаю документацию на ПО, иногда со словарём»), то даже желательны — я могу, наверное, так что-нибудь написать, что человек хорошо знающий английский или вообще не поймёт, или поймёт неправильно, если не учился в советской школе :) А другой «полиглот» вставит какую-нибудь идиому, поговорку или цитату, над которой вся команда полдня будет думать, пытаясь перевести дословно
                          • UFO just landed and posted this here
                              +1
                              Если уж пишете на русском, пишите на нём правильно: «русский», «английский», всё с маленькой буквы.
                              • UFO just landed and posted this here
                        +3
                        PHPUnit + Code Sniffer + PMD незаменимы в большом (и не очень) PHP-проекте в связке с системой непрерывной интеграции. А если ещё и работаем по Scrum — сказка
                        +1
                        Дичайший язык изложения, особенно с деепричастными оборотами, — сильно похоже на корявый перевод. И ни одного комментария автора.

                        А по теме: рекомендую еще статью Бергманна Quality Assurance Tools For PHP — там описана целая система инструментов, включая и phpcs.
                          0
                          Приношу извинения автору: прочитал другие статьи — стиль, вроде, тот же самый :) Ошибки есть, что не уменьшает пользы самих статей.
                          0
                          кстати, для Eclipse есть замечательный плагин www.phpsrc.org/
                            0
                            А можно как-то настроить чтобы проверялся только добавленый/измененный код?
                              0
                              Так хук и должен проверять только файлы в коммите.
                                0
                                У git'a в коммит попадают только новые/изменённые файлы.
                                  0
                                  Это да, но я не хочу проверять весь файл. Мне надо только кусок.
                                  Скажем так: есть файл на 10 тыс. строк, его рефакторят. Но за 1 раз отрефакторить все невозможно!
                                    +1
                                    Теперь понял.
                                    <?php
                                    много кода
                                    // @codingStandardsIgnoreStart
                                    здесь тоже много кода, но он не будет проверен
                                    // @codingStandardsIgnoreEnd
                                    дальше много кода
                                    

                                      0
                                      Вот, то что нужно. Круто. Спасибо!
                              0
                              собираемся у себя в проекте использовать эту систему, пока только 2 разработчика, но по идее чем раньше начнешь, тем чище будет код =)
                                0
                                Лучше бы он, сука, русский язык проверял. Извините.
                                  0
                                  Стандарт Zend что в комплекте не стандарт соответствует стандарту описанному на офф. сайте, обещали что-то сделать к 2.0 в этом направлении.
                                    +1
                                    Ах да еще можно php -l воткнуть чтобы синтаксис проверялся.
                                    0
                                    У кого-нибудь получилось установить pre-commit хук под windows?
                                    0
                                    Как долго я набирал свой Standard для этого зверя! Не нашёл в природе ни одного конструктора, хотя оный был бы полезен многим.
                                      0
                                      Вы конструктор так и не нашли после коммента?
                                        0
                                        И не искал. Не возникло необходимости, так как вся работа и так была проведена.
                                      0
                                      Можно при сохранении файла проверять. Что бы разработчик сразу делал правки, а не один раз при коммите, перебирая все файлы.
                                      Плюс, проверка при сохранении, как по мне, приучает писать код правильнее.
                                        0
                                        Если кому-то инттересно, то я в своём блоге описал решение для Windows.

                                        Only users with full accounts can post comments. Log in, please.