Рефакторинг по методу «heavy clay»: вынести «плохой» код в отдельный файл и довести до методов
Задача и когда подход уместен
Нужно исправить ошибки в старом PHP‑коде с минимальными временными затратами, когда нет нормального покрытия тестами и полностью «вырезать» логику в новый сервис с первого дня нереалистично. Речь про длинные процедурные участки, запутанный поток и переменные, которые живут не только внутри блока, но и дальше по скрипту и во включаемых файлах.
Симптомы «тяжёлой глины»
- один огромный блок в процедурном стиле;
- переменные из «плохого» фрагмента читаются ниже по коду или в других include;
- нет автотестов, которые подтвердили бы эквивалентность до и после.
В такой ситуации автор оригинальной заметки предлагает технику «heavy clay refactoring»: результат каждого шага сверяется с оригиналом запуском всего приложения (интеграционная проверка вместо юнита).
Шаг 1 — выделить участок и развести по файлам
Находите условие, внутри которого лежит проблемный код. Копируете тело в два файла, например origin.php (как было) и modify.php (рабочая копия для правок). В основном месте оставляете ветвление:
if (count($getParms) > 0) {
$way = 0;
include $way === 1 ? 'origin.php' : 'modify.php';
}Переключение ведётся переменной $way: сначала убеждаетесь, что поведение совпадает с оригиналом, затем переводите $way на «новую» версию.
Вынос в отдельный файл даёт чёткие границы метода: сложнее случайно править «не тот» экран длинного файла, проще навигироваться и видеть, как кусок «перерождается».
Шаг 2 — зависимости в modify.php
Нужно понять все внешние переменные, которые участок читает и какие значения оставляет дальше по приложению — в том числе в других подключаемых файлах.
- для обзора текущей области видимости можно временно смотреть
get_defined_vars()(осторожно: шумно на больших скриптах); - грубый эвристический приём — после
includeпробоватьunset($var1, $var2): если ничего не сломалось, переменная, скорее всего, локальна для этого куска (метод неточный при высокой циклической сложности); - внутренние имена временно уникализируют, например
$var→$_var, чтобы не пересечься с окружением.
По мере разбора роли переменных полезно явно комментировать контракт файла:
if (count($getParms) > 0) {
$way = 1;
include $way === 0 ? 'origin.php' : 'modify.php';
// IN: $getParms, $seriesAll
// OUT: $existsTags, $series
}Шаг 3 — оформить в метод(ы)
Когда границы ясны, modify.php можно превратить в метод класса: элементы из блока IN становятся параметрами, из OUT — возвращаемыми значениями.
Если наружу отдаётся несколько величин, варианты такие: один метод возвращает массив и вызывающий код разворачивает его через list() / деструктуризацию, либо — семантически часто лучше — два узких метода, каждый возвращает одну сущность, даже если пока оба внутри подключают один и тот же legacy‑файл:
$existsTags = $this->heavyClayMethodTags($getParms, $seriesAll);
$series = $this->heavyClayMethodSeries($getParms, $seriesAll);private function heavyClayMethodTags(array $getParms, $seriesAll)
{
include __DIR__ . '/legacy/modify.php';
return $existsTags;
}
private function heavyClayMethodSeries(array $getParms, $seriesAll)
{
include __DIR__ . '/legacy/modify.php';
return $series;
}Это временное дублирование: следующий шаг — развести общий код по двум реализациям; общие переменные часто естественно поднять в свойства объекта ($this->…).
Связка с 1С‑Битрикс и продакшеном
В типичном битриксовом легаси важно не оставлять отладочный вывод и временные include на боевом домене: по завершении рефакторинга файлы‑заглушки удаляют, логику собирают в классы/сервисы проекта, ошибки ведут через принятый в инфраструктуре логгер. Проверяйте сценарии на копии сайта и с резервным копированием перед массовыми перестановками.
Кратко
- Heavy clay — поэтапное выделение «грязного» кода в файлы, переключение флагом, явные IN/OUT, затем методы.
- Рефакторинг подтверждается прогоном приложения, а не только чистотой стиля в редакторе.
- Цель промежуточных шагов — выйти из процедурного «месива» к структуре (ООП, ясные границы), после чего убрать временные include и дубли методов.
Не хотите копаться сами?
Починю за 1-3 дня. Без предоплаты — оплата по результату.
15+ лет опыта с 1С-Битрикс · Без предоплаты · 7 дней гарантии