Dark mode switch icon Light mode switch icon

PHP Rector и как он вам [не] поможет

• 1 минут чтобы прочитать

Все, кто планировал переход на новые версии PHP слышали о проекте Rector для автоматизации рефакторинга и адаптации новых фич. Каждый кто завершал такой переход может рассказать пачку историй о том как и когда всё пошло не по плану.

Что такое Rector

Rector это инструмент автоматизации рефакторинга и апгрейда кодовой базы. Он поможет с базовыми вещами вроде добавления тайп-хинтов и конвертацией PhpDoc в аттрибуты. Более того, типичные сценарии объединены в наборы правил: например набор Php52 для миграции на PHP 5.2 содержит сразу два правила: ContinueToBreakInSwitchRector и VarToPublicPropertyRector, которые заменят continue на break в switch-конструкциях и заменят ключевое слово var на public в объявлении полей класса, соответственно. Удобно!

В чём подвох?

Давайте рассмотрим типичный пример апгрейда PHP между мажорными версиями - ведь именно это опаснее всего и именно в таких случаях мы хотим подстелить соломку. К примеру, пусть мы хотим обновить наш страшный legacy проект с PHP 5.6 на PHP 7.0. Смотрим на несовместимые изменения в PHP 7.0 и видим среди прочих:

и др.

Что лишнего в Rector?

В то же самое время в наборе правил Rector для Php70 есть следующие штуки:

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

Какие есть альтернативы?

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

Важный урок, который я вынес из общения с этими инструментами: эти инструменты не сделают волшебно, бесшовно и безболезненно.

Некоторые автоматизированные правки могут прикрыть вам тыл, тогда как другие внесут ошибки ковариантности и контравариантности в наследовании. Такие ошибки интерпретатор отловит при первой же попытке запустить проект, но что если ошибки могут проявиться только в райнтайме? Например, добавленный declare(strict_types=1); сделает ваш код более строгим и там где раньше срабатывало приведение типов, теперь появится ошибка!

Так что делать-то?

В конечном итоге мы хотим без ошибок выкатить в продакшен код на новой версии языка.

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

Если тестами обкладываться сложно, долго и дорого (потому что у вас legacy) - найдите ключевой функционал и покройте тестами хотя бы его. Вероятно чтобы покрыть его тестами вам будет нужно сначала вручную критические части кода хорошенько отрефакторить и например уложить в классы с полноценным внедрением зависимостей, вынесением низкоуровневой работы с БД или сетью в отдельные классы, внедрением работы с интерфейсами и абстракцией вместо конкретных реализаций, и в целом обмазывании себя типизацией со всех сторон.

И все проблемы автоматических инструментов сводятся к тому что они могут быть лишь настолько умными, насколько это возможно. Если ваша функция работы с БД принимает аргумент $ref типа int[]|string[]|false|null|mixed, то поможет вам только собственный опыт в том как этот клубок распутать и что делать дальше, потому что применение автоматизации здесь совершенно невозможно.

В заключение

Может показаться что я утверждаю что такие инструменты как Rector, psalm и phpstan не нужны, однако это совершенно не так. Я лишь подсвечиваю тот момент, которому не всегда деляют много внимания в диферамбах о том, как быстро и легко обновить весь проект с егозависимостями.

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

Успешного вам обновления.

Впервые опубликовано от Эдуард Сухарев