Yandex Metrika
sanches.free 1 просмотр

Рефакторинг по методу «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 дней гарантии