Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Цель статьи - помочь разработчикам которые много слышали про статический анализ, но пока что так и не поняли что это такое и с чем его едят.
Статический анализ:
Анализ программного обеспечения, производимый без реального выполнения исследуемых программ, процесс выявления ошибок и недочетов в исходном коде программ. Список языков для которых существуют статические анализаторы кода достаточно велик, например это Си, Си++, C#, Java, Ada, Fortran, Perl, Ruby и т.д. Компиляторы различных языков программирования во время своей работы так же запускают статические анализаторы (как правило усеченные версии) которые находят ошибки. Т.о. использование статического анализа, в поиске ошибок, приближает/приравнивает PHP к компилируемым языкам программирования.
Сообщество PHP прикладывает значительные усилия в сторону развития статического анализа, так типы mixed и never были добавлены для лучшего анализа программами статического анализа.
Необходимость статического анализа:
Статический анализ позволяет найти уйму различных проблем в коде, начиная от неправильного использования конструкций языка, заканчивая опечатками. При проведении code review позволяет сосредоточиться на просмотре реализации логики программы, а не на поиске синтаксических ошибок, опечаток, ошибок в данных, мертвый код и т.п.
Задачи, решаемые программами статического анализа кода:
Выявление ошибок в программах.
Рекомендации по оформлению кода.
Подсчет метрик.
Преимущества статического анализа кода:
Полное покрытие кода. Статические анализаторы проверяют даже те фрагменты кода, которые получают управление крайне редко.
Статический анализ не зависит от используемого компилятора и среды, в которой будет выполняться скомпилированная программа. Это позволяет находить скрытые ошибки, которые могут проявить себя только через несколько лет.
Можно легко и быстро обнаруживать опечатки и последствия использования Copy-Paste.
Недостатки статического анализа кода:
Статический анализ, как правило, слаб в диагностике утечек памяти и параллельных ошибок.
Программа статического анализа предупреждает о подозрительных местах. Это значит, что на самом деле код, может быть совершенно корректен.
Какой анализатор выбрать?
На данный вопрос однозначного ответа нет! Дело в том, что инструменты статического анализа постоянно развиваются и если сегодня один анализатор впереди планеты всей, то завтра он может быть последним. Например компания Badoo в своей статье пишут о том, что они используют сразу три статических анализатора. В сообществе PHP большую популярность получил Psalm, но мой выбор пал на PHPStan и связано это с количеством спонсоров у проекта.
Автоматизация:
Запуск программ статического анализа возможно добавить в процесс CI (CI/CD), тем самым не допустить попадания некачественного кода в общую ветку разработки.
Пример (не панацея) bash скрипта:
#!/bin/bash
vendor/bin/phpstan analyse -c phpstan.neon
if [ $? -eq 0 ]
then
echo "Successful checks PHPStan"
exit 0
else
echo "ERRORS script PHPStan" >&2
exit 1
fi
PHPStan
Оф. сайт: https://phpstan.org/
GitHub: https://github.com/phpstan/phpstan
Ниже опишу простые примеры использования инструмента. За более подробной информацией обращайтесь к страницам официальной документации!
Установка:
composer require --dev phpstan/phpstan
Запуск:
vendor/bin/phpstan analyse [options] [--] [<paths>...]
example:
vendor/bin/phpstan analyse -l 5 -c phpstan.neon ./src/
Настройка PHPStan:
Все опции запуска PHPStan можно вынести в файл конфигурации phpstan.neon и запускать скрипт следующим образом:
vendor/bin/phpstan analyse -c phpstan.neon
Пример файла конфигурации PHPStan:
parameters:
level: 5
paths:
- src
Уровни анализа (-l | --level)
*оставил без перевода, т.к. боюсь неправильно донести их смысл.
*уровень по умолчанию 0, т.е. если в параметрах запуска не указать уровень, то будет выбран уровень 0
Уровень 0: basic checks, unknown classes, unknown functions, unknown methods called on $this, wrong number of arguments passed to those methods and functions, always undefined variables.
Уровень 1: possibly undefined variables, unknown magic methods and properties on classes with __call and __get.
Уровень 2: unknown methods checked on all expressions (not just $this), validating PHPDocs.
Уровень 3: return types, types assigned to properties.
Уровень 4: basic dead code checking - always false instanceof and other type checks, dead else branches, unreachable code after return; etc.
Уровень 5: checking types of arguments passed to methods and functions.
Уровень 6: report missing typehints
Уровень 7: report partially wrong union types - if you call a method that only exists on some types in a union type, level 7 starts to report that; other possibly incorrect situations
Уровень 8: report calling methods and accessing properties on nullable types
Уровень 9: be strict about the mixed type - the only allowed operation you can do with it is to pass it to another mixed
Важно:
PHPStan при своем запуске во многом ориентируется на typehints, но большей частью проверки операются на PHPDocs!
Несколько примеров PHPDocs
Проверка полей массива (если вы их используете):
/**
* ......
* @param array{roles: array, name: string, login: string, password: string} $data
* ......
*/
Проверка поля класса:
use App\...\Roles;
// ......
/**
* @var Roles[] - пример массива объектов типа Roles
*/
private array $roles;
Проверка возвращаемого функцией результата:
use App\...\Roles;
// .....
/**
* .....
* @return Roles - пример возвращаемого результата
*/
function fn(): Roles;