Рефакторинг по методу "heavy clay refactoring"

Цель: исправлении ошибок с минимизацией временных затрат.

Симпомы: метод написан в процедурном стиле, очень длинный, код запутан, переменные проблемного участка используются далее по скрипту во включаемых файлах. Отсутствуют тесты контроля и проверки.

Решение: техника «heavy clay refactoring», результаты рефакторинга сравниваются с оригиналом запуском всего приложения.

Выявлен проблемный участок кода

bad.php
if (sizeOf($getParms) > 0) {
 /* Bad code */
}

Копирование «Bad code» в origin.php и modify.php (для удобства).

bad.php
if (sizeOf($getParms) > 0) {
  $way = 0;
  include($way == 1 ? 'origin.php' : 'modify.php');
}
  • Теперь переключение осуществляется в переменной $way.
  • Вынос в отдельный файл позволяет четко выделить границы метода. Невозможно случайно внести исправления «не там», особенно когда код на несколько экранов.
  • Удобно перемещаться по тексту в файле, ощущая его перерождение в метод.

Работа с файлом ''modify.php''

Выявление зависимостей

Выявляем все «внешние» переменные, которые будут далее использоваться по коду. Для этого смотрим их далее по всем файлам.

Вывод всех переменных в текущей области видимости: get_defined_vars()

Также возможно сделать варварским способом unset($var1, $var2) после include в bad.php - если ничего не сломалось, переменная «локальна» для этого участка кода. Но необходимо осознавать потенциальную неточность такого способа, учитывая цикломатическую сложность.

Переписываем «внутренние» переменные по принципу $var1 => $_var1 или иным способом. Это делаем временно, или так и оставим в дальнейшем.

По ходу выявления роли переменных вносим в файл изменения:

bad.php
if (sizeOf($getParms) > 0) {
  $way = 1;
  include($way == 0 ? 'origin.php' : 'modify.php');
  // IN: $getParms, $seriesAll
  // OUT: $existsTags, $series
}

Оформление кода в метод

Поздравляем: после этих манипуляций файл modify.php теперь возможно оформить в отдельный метод!

IN - аргументы метода, OUT - результат его работы.

Так как на выходе 2 параметра, то на выбор:

  • будем возвращать массив совместно с конструкцией list()
  • оформим 2 метода, что лучше, но не всегда так легко

Оформление кода в два метода (и более)

Вместо возвращения массива значений надо подумать о возможности использования двух (в нашем случае) или более методов, каждый из которых возвращает одно значение:

bad.php
$existsTags = $this->heavyClayMethodTags($getParms, $seriesAll);
$series = $this->heavyClayMethodSeries($getParms, $seriesAll);
bad.php
private function heavyClayMethodTags($getParms, $seriesAll) {
  include('legacy/modify.php');
  return $existsTags;
}
 
private function heavyClayMethodSeries($getParms, $seriesAll) {
  include('legacy/modify.php');
  return $series;
}

Оба метода эксплуатируют один и тот же код, но возвращают по одной переменной. Это - временное решение. В дальнейшем необходимо подумать о разделении их общего кода на две части. При этом скорее всего выявляется переменные, которые используются и в первом, и во втором, их лучше вынести на уровень объекта $this->var.

В итоге мы как минимум избавились от «месева» и встали на путь ООП.

Окончательно рефакторим код, избавляемся от файлов modify.php и origin.php.