Вызывает интерес ваш технический прогресс.
Как у вас там сеют брюкву, с кожурою, али без?

© «Сказка про Федота-стрельца, удалого молодца», Леонид Филатов 

Программист — творческая профессия. Мы создаем что-то новое, руководствуясь своими знаниями, внутренним пониманием качества и поставленными дедлайнами. Дедлайны и знания пока оставим в стороне и сосредоточимся на качестве.

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

Ниже делимся статьей 2017 года.

«Что такое плохой/хороший код» — вопрос риторический. В нашей статье под качественным кодом мы будем понимать:

  • корректный с точки зрения платформы (без запросов к БД в шаблонах компонентов, запросы к БД с использованием индексов),

  • совместимый с актуальными версиями PHP (5.6, 7.0),

  • соответствующий единым стандартам кодирования , принятым в команде,

  • без ляпов (запросы к БД в цикле, запросы к внешним системам на хитах),

  • без уязвимостей (XSS, CSRF и т.д.).

С написанием хорошего кода отлично справляются самые опытные из нас: тимлиды. Но их мало (в штуках), а их время стоит дорого. У менее опытных разработчиков бывают проблемы со всем вышеперечисленным.

Как обеспечить качество кода с точки зрения методологии известно. Нужно развивать в команде процессы Continuous Integration: версионирование, тестирование, code review. Мы решили разобраться: какие инструменты подойдут для автоматизации code review при промышленной веб-разработке на PHP. А заодно проверим, как найденные инструменты оценят код нашего собственного сайта и нескольких решений из Marketplace 1С-Битрикс.

Инструменты для автоматизации code review PHP

Методика поиска инструментов

Мы нашли на github.com и packagist.org самые оцениваемые и самые скачиваемые проекты, связанные с анализом кода PHP. В обзор мы включили только надежные (созданы не вчера), поддерживаемые (есть сообщество и контрибьюторы) и популярные (количество звезд-”лайков”).

Выделили три категории инструментов:

  • проводящие анализ кода  с целью поиска проблемных мест;

  • проверяющие совместимость версий PHP 5-7;

  • проверяющие уязвимости.

Инструменты для анализа PHP-кода

PHP Code Sniffer анализирует PHP, CSS и JavaScript-файлы на соответствие стандартам кодирования, находит и исправляет ошибки. Стандарт представляет собой совокупность sniff-файлов, задающих правила. Количество установок анализатора с 2016 года превысило ~330 тысяч. Использование зафиксировано в ~7500 проектах.

PHP CS Fixer - инструмент, разработанный автором фрэймворка Symfony. Обнаруживает и исправляет ошибки в коде. Помимо следования стандартам кодирования (PSR-1, PSR-2 и др.). Позволяет писать собственные правила. Поддерживает PHP 7. Проект стремительно развивается и приобретает популярность как среди пользователей (~325 тысяч установок с начала 2016 года), так и у разработчиков (с 2017 года используется в ~1500 проектах).

PHP Mess Detector определяет ошибки кода, неоптимальные и усложненные места, неиспользуемые переменные, методы, свойства. Позволяет создавать пользовательские правила. Поддерживает PHP 7. Сохраняет отчеты в трех форматах: текстовый, html, xml. С 2016 года пользователи установили ~315 тысяч раз, используется в ~2000 проектах.

PHP Metrics — инструмент статического анализа для PHP. Выдает информацию о проекте и используемых классах в виде сгенерированного сайта. Поддерживает PHP 7. С 2016 года зарегистрировано ~260 тысяч скачиваний.

PHP Static Analysis Tool анализирует количество и типы параметров, передаваемых конструкторам, методам и функциям; типы, возвращаемые методами и функциями и т.д. Инструмент включает поддержку PHP 7 и предоставляет написание собственных правил. Количество скачиваний с 2016 года ~150 тысяч раз, использован разработчиками в ~200 проектах.

PHP Copy Paste Detector выдает информацию о дублированных участках кода. Проект набирает популярность (количество установок с 2016 года составляет ~100 тысяч раз, используется в ~1000 проектах).

Phan — статический анализатор для PHP. Проверяет определение и доступность методов, функций, классов, traits, интерфейсов, констант, свойств и переменных, обнаруживает неиспользуемый код, проверяет код на обратную совместимость php7 к php5. С 2016 года зафиксировано ~80 тысяч раз скачиваний.

PHP Dead Code Detector сообщает пользователю о функциях и методах, которые не используются в коде. Развитие проекта было остановлено в 2015 году. Начиная с 2016 года, количество установок пошло на спад.

Qafoo Quality Analyzer — инструмент, предназначенный для визуализации метрик исходного кода. Начиная с 2015 года, инструмент установлен пользователями ~4800 раз.

Инструменты для контроля совместимости кода с разными версиями PHP

PHP Compatibility — набор правил для PHP Code Sniffer, которые проверяют совместимость текущего кода с другими версиями PHP, включая PHP 7. Начиная с 2016 года, инструмент установлен пользователями ~22 тысячи раз.

PHP 7 Compatibility Checker — инструмент для проверки кода PHP 5.3 – 5.6 на совместимость с PHP 7. Находит потенциальные проблемы в коде и генерирует отчеты, содержащие имена файлов, номера строк и краткое описание проблемы. При этом проблемы двух типов: ошибки, вызывающие серьезные проблемы (фатальная ошибка, ошибка синтаксиса и т.д.) и предупреждения, приводящие к логическим ошибкам. Начиная с 2016 года, инструмент установлен пользователями ~15 тысяч раз. 

Инструменты для поиска уязвимостей в PHP-коде

К сожалению нам не удалось найти ни одного проекта для анализа уязвимостей в PHP-коде, который заслуживал бы внимания. А жаль…

Вывод простой: не надейтесь что нажатием пары кнопок вы сможете найти все уязвимости в своем коде. Вместо этого изучите и применяйте правила безопасности, специфичные для вашей CMS/фреймворка .

Что на выходе

PHP CS Fixer

Результат запуска PHP CS Fixer - единый патч-файл, в котором указываются:

  • файлы, в которых обнаружены ошибки;

  • правила, которые сработали;

  • изменения, затронувшие строки файла: удаленные, оставшиеся без изменений, добавленные строки.

Пример:

PHP Code Sniffer

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

Пример:

PHP Mess Detector

Отчет в PHP Mess Detector генерируется в одном из трех форматов: текстовый, html, xml. Полученный файл содержит информацию об обнаруженных проблемах в файлах. Проблема описывается начальной и конечной строкой, сработавшим правилом и поясняющим сообщением.

Пример:

PHP Dead Code Detector

Отчет в PHP Dead Code Detector - это список неиспользуемых функций и методов с указанием количества занимаемых строк, файла и номера строки в файле.

Пример:

PHP Copy Paste Detector

В отчет по PHP Copy Paste Detector заносятся файлы, в которых дублируются строки.

Пример:

PHP Static Analysis Tool

В отчете PHP Static Analysis Tool для каждого файла, в котором обнаружены ошибки, указывается номер строки в файле и описание ошибки. В конце отчета приводится общее количество найденных ошибок.

Пример:

Инструмент показал себя не лучшим образом и был исключён из анализа. Почему -- читайте в конце статьи.

Phan

Результат работы в Phan может быть выведен в следующих режимах: 'text', 'json', 'csv', 'codeclimate', 'checkstyle', и 'pylint'. В режиме 'csv’ выводятся следующие столбцы: файл, строка, категория ошибки, phan-тип ошибки, сообщение.

Пример:

PHP Compatibility

Результатом PHP Compatibility является список ошибок и предупреждений, найденных при проверке на совместимость с указанной версией PHP.

Пример:

PHP 7 Compatibility Checker

При проверке на совместимость PHP 7 Compatibility Checker генерирует список нарушений в коде: указывается файл, строка, поясняющее сообщение и ошибочный код.

Пример:

Qafoo Quality Analyzer

Qafoo Quality Analyzer генерирует отчет в формате xml, где для каждого файла приводится список обнаруженных ошибок с описанием.

Пример:

PHP Metrics

PHP Metrics по окончании своего выполнения генерирует количественный отчет по метрикам и визуализирует полученные данные в виде созданного сайта.

Пример:

Итоговая таблица сравнения инструментов

Что в отчёте

Инструмент объясняет, в чём ошибка

Что считать? Какая метрика?

Своя конфигурация правил, свои правила

PHP CS Fixer

Патч-файл с перечнем рекомендованных изменений

Нет

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

Да

PHP Code Sniffer

Таблицы с перечнем ошибок и отметкой, какие можно исправить автоматически

Да

1. Количество ошибок2. Количество неисправимых ошибок

Да

PHP 7 Compatibility Checker

Единый отчёт, по каждой ошибке: файл, строка, объяснение сути ошибки

Да

Количество ошибок

Нет

PHP Compatibility

Единый отчёт, по каждой ошибке: файл, строка, объяснение сути ошибки

Да

Количество ошибок

Да

PHP Copy Paste Detector

Единый отчёт с перечнем мест, где повторяется тот или иной участок кода

Да*

1. Количество “клонов”2. Количество повторяющихся строк

Нет

PHP Dead Code Detector

Перечень неиспользуемых функций и методов, файл с их объявлением и количество строк кода

Да*

1. Количество неиспользуемых функций/методов2. Количество строк, которые занимают такие функции/методы

Нет

PHP Mess Detector

Перечень ошибок: файл, строка, правило

Да

Количество ошибок

Да

PHP Metrics

Перечень ошибок: файл, строка, правило

Да

Количество ошибок

Да

PHP Static Analysis Tool

Перечень ошибок: файл, строка, правило

Да

Количество ошибок

Да

Qafoo Quality Analyzer

Перечень ошибок: файл, серьёзность ошибки, строка, правило

Да

1. Количество ошибок2. Количество предупреждений

Да

Phan

Перечень ошибок: файл, серьёзность ошибки, строка, правило

Да

1. Количество ошибок категории low2. Количество ошибок категории normal3. Количество ошибок категории critical

Да

* -- у инструмента единственное назначение, объяснения ошибок не требуется

Апробация инструментов на 1С-Битрикс

Каждый из инструментов был опробован на коде:

  • тиражных решений из Marketplace 1С-Битрикс (3 платных решения, 5 бесплатных),

  • современного сайта ИНТЕРВОЛГИ (на 1С-Битрикс),

  • устаревшего сайта ИНТЕРВОЛГИ (на самописной CMS).

Прежде чем подвести итоги, сообщаем что инструмент PHP Static Analysis Tool был дисквалифицирован и исключён из соревнования. Причина — 90% его ошибок это “неизвестная константа”, “неизвестный метод”, “неизвестный класс” ядра Битрикса (мы проверяли только папку с решением). То есть, чем больше решение использовало API Bitrix, тем больше в нём было “ошибок”. Попытка добавить ядро Битрикса в анализ привела к аварийному завершению работы инструмента с ошибкой “Класс Bitrix\Main\SystemException объявлен дважды”. И действительно, в ядре множество классов объявленных в разных местах. Решив “а давайте временно уберём этот класс”,  получили другую ошибку. Убрали её -- получили третью и т.д. Попытки прекратили после 13-ой итерации.

Теперь к итогам сравнения решений. Мы считали не общее количество ошибок, а количество ошибок на 1000 строк кода.

ВАЖНО! Чтобы получить максимально показательную картину, мы суммировали ВСЕ замечания ВСЕХ 15 инструментов. Не удивляйтесь, что число ошибок часто больше числа строк.

Места распределились таким образом:

  1. Старый сайт ИВ (703 ошибки  на 1000 строк)

  2. 1С-Битрикс: Современный интернет-магазин (1457 ошибки на 1000 строк)

  3. Новый сайт ИВ (1881 ошибки на 1000 строк)

  4. 1С-Битрикс: Корпоративный сайт (1998 ошибки на 1000 строк)

  5. Платный ИМ (2506 ошибки на 1000 строк)

  6. Платный ИМ (2525 ошибки на 1000 строк)

  7. Платный ИМ (2682 ошибки на 1000 строк)

  8. Бесплатный ИМ (3542 ошибки на 1000 строк)

  9. 1С-Битрикс: Информационный портал (3578 ошибки на 1000 строк)

  10. Бесплатный ИМ (7361 ошибки на 1000 строк)

ВАЖНО! Чтобы получить максимально показательную картину, мы суммировали ВСЕ замечания ВСЕХ 15 инструментов. Не удивлятесь что число ошибок часто больше числа строк.

Подробные результаты приведены в таблице .

То, что лучшим стал старый сайт ИВ нас искренне удивило — мы ожидали прямо противоположного результата. У этого проекта 2 рекордных показателя — количество ошибок и количество строк кода. Так и вышло, что на 1000 строк кода проблем меньше всего. Но старый сайт — “почётный” участник, посмотрим на реальные результаты.

Настоящий победитель нашего исследования — 1С-Битрикс: Современный интернет-магазин. Что можно о нём сказать по результатам исследования:

  1. Из 1000 строк в этом решении — в среднем 17 строк “копипасты”.

  2. В 2 строках есть вызовы устаревшего API.

  3. Есть 6 нарушений при работе с методами и полями.

  4. 284 строки кода можно отформатировать автоматически с помощью PHP CS Fixer.

  5. Почти нет проблем с совместимостью PHP.


Второе место получает новый сайт ИНТЕРВОЛГИ . Разрабатывавшийся силами всей компании в разные годы, он как-то смог не уронить высокую планку качества, заданную компанией 1С-Битрикс.

Третье место — 1С-Битрикс: Корпоративный сайт . Снова 1С-Битрикс показал всем, как надо делать сайты.

Худшим решением по мнению “жюри” признан бесплатный ИМ из ТОПа маркетплейса.

Добавим ложку дёгтя в бочку мёда компании 1С-Битрикс — вторым с конца оказалось тоже их решение, на которой выросло не одно поколение программистов.

Предпоследнее место — 1С-Битрикс: Информационный портал

Что касается инструментов... По-настоящему полезным, почти без оговорок, показал себя PHP Copy Paste Detector — на нашем сайте, например, он находил блоки кода по 50-100 строк, повторяющиеся в 2-3 местах. Единственная оговорка -- часто он ругается на вызовы вложенных компонентов (например, catalog.element внутри catalog).

Отличить настоящие ошибки от ложного срабатывания было сложно в PHP Dead Code Detector — тут оказывались обработчики событий, агенты, конструкторы и инсталляторы, которые явным образом нигде не вызываются в коде или вызываются извне модулей.

Насчёт PHP Static Analysis Tool уже было сказано, что почти все его ошибки были “ложными срабатываниями”.

Хорошо показал себя PHP Mess Detector: отследил мелкую, но неприятную ошибку статического вызова динамических методов и наоборот. В то же время он ругался на каждый else, так как  “else is never necessary and you can simplify the code to work without else”.

Главный “хлеб” таких инструментов, как Qafoo Quality Analyzer, PHP Code Sniffer,  PHP CS Fixer: превышение длины строк, переводы строк в конце файла, короткие-длинные открывающие php-теги, пробелы после ключевых слов if, for, while и т.п. Из предлагаемого инструментами набора правил мы выбрали наиболее похожие на стандарт оформления кода 1С-Битрикс, но всё равно получили около 50% ложных срабатываний.

Полезную статистику предоставляет PHP Metrics, если в вашей команде есть понимание, сколько операторов для класса уже “много”, а сколько — “ещё нормально”. Аналогично с цикломатической сложностью.

Вывод

Смысл затеи с инструментами проверки качества кода был в том, чтобы выяснить какой инструмент стоит выбрать для автоматизации Code Review. Эту цель мы достигли и свой выбор остановили на  PHP CS Fixer и PHP Code Sniffer. Они адекватны задаче, популярны, развиваются, их можно расширять, и есть масса уже готовых тестов. Осталось только адаптировать их к реалиям разработки сайтов на 1С-Битрикс: Управление Сайтом.

Теперь, с той же обстоятельностью и упорством, с которыми мы писали этот обзор, будем внедрять эти инструменты в свою командную разработку.

Соавтор статьи: Анатолий Ерофеев.

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


  1. Arris
    02.09.2021 20:41
    +7

    совместимый с актуальными версиями PHP (5.6)

    Это какая-то шутка?

    Даже security fixes для 5.6 перестали выпускать 2.5 года назад.

    https://www.php.net/supported-versions.php

    Из какого года вы скопирайтили эту статью?


    1. stepan_ovchinnikov Автор
      02.09.2021 21:52

      пардон, статья действительно написана несколько лет назад
      указали это в тексте

      сути не меняет вроде как


      1. SerafimArts
        02.09.2021 21:58
        +6

        сути не меняет вроде как

        Почему же? Сейчас в тренде psalm и phpstan, но ни про тот, ни про другой в статье ни слова.


        P.S. С другой стороны — даже представленных инструментов достаточно, чтобы сделать вывод о том, что в коде битрикса полная помойка. Однако 1с вроде как "новое ядро" представляли недавно, где всё вроде как лучше стало.


      1. ollisso
        03.09.2021 12:49

        За 4 года - сильно меняется ландшафт в мире PHP.

        Часть модулей уже не актуально, например проверки совместимости с пхп 7.0. Сейчас уже нужен модуль проверки совместимости с 8.0 :)


      1. Arris
        03.09.2021 22:55

        Ну я конечно до сих пор встречаю проекты на древних версиях PHP. Иногда даже на 5.2 (то есть mysql_connect и совершенно кошмарное легаси, которое "ну сделайте пожалуйста что-нибудь, чтобы оно заработало").

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


  1. SerafimArts
    02.09.2021 21:57

    del


  1. tzlom
    03.09.2021 01:00
    +5

    Попытка добавить ядро Битрикса в анализ привела к аварийному завершению работы инструмента с ошибкой “Класс Bitrix\Main\SystemException объявлен дважды”. И действительно, в ядре множество классов объявленных в разных местах.

    Я правильно понимаю что тулза была забанена за обнаружение говнокода?


  1. lleo_aha
    03.09.2021 10:11
    +1

    PSALM ещё был забыт. Хотя раз статья давнишняя - может его тогда не было