Большинство команд разработчиков хотят привести свою кодовую базу в лучшее, более удобное для обслуживания состояние. Но какое определение лучше выбрать? Во многих случаях нет необходимости углубляться в доменно-управляемый дизайн (DDD) для достижения этой цели. Иногда это даже контрпродуктивно. Но один из самых основных наборов принципов уже может помочь каждой команде: чистый код.
Цель
В книге « Чистый код » Роберта С. Мартина обобщено множество простых и расширенных улучшений, позволяющих получить лучший, понятный и, следовательно, более понятный код. Давайте возьмем следующий фрагмент кода в качестве примера:
public function getJobs($date)
{
$ret = array();
$res = $this->db->query(
'SELECT * FROM jobs WHERE year=' . date('Y', $date) . ' AND month='
. date('m', $date)
);
$res = $res->fetchAll();
foreach ($res as $data) {
$j = new Job(/* $data['...'] */);
$j->rev = $j->time * $j->euro;
$ret[] = $j;
}
return $ret;
}
Похоже, что цель этого и без того простого метода — вернуть задания на определенную дату. Хотя это намерение очевидно, прочитать метод и понять, как он выполняет свою работу, не так просто. После этого алгоритм выглядит довольно просто: сначала он выбирает некоторые данные из базы данных, затем он подготавливает объекты заданий, вычисляет некоторые дополнительные данные и возвращает объекты.
Но время, потраченное на понимание этого простого фрагмента кода, потрачено впустую. Как разработчик, анализируя свою повседневную работу и работу других людей, вы заметите, что тратите гораздо больше времени на чтение и понимание кода, чем на его написание.
Низко висящим плодом будет просто переименовать локальные переменные для улучшения читабельности:
public function getJobs($date)
{
$jobs = array();
$statement = $this->db->query(
'SELECT * FROM jobs WHERE year=' . date('Y', $date) . ' AND month='
. date('m', $date)
);
$rows = $statement->fetchAll();
foreach ($rows as $row) {
$job = new Job(/* $row['...'] */);
$job->rev = $job->time * $job->euro;
$jobs[] = $job;
}
return $jobs;
}
Переменная, ранее известная как $ret
$jobs
Это имя теперь ясно указывает на то, что мы можем ожидать от него: список рабочих мест. Кроме того, это не может быть легко перепутано с $ret
$statement
$rows
Теперь мы понимаем, что происходит намного лучше.
Еще один шаг к улучшению читабельности — разбить код на логические части, которые объединяются, и сделать его более похожим на книгу или газету, где абзацы являются информационными группами:
public function getJobs($date)
{
$statement = $this->db->query(
'SELECT * FROM jobs WHERE year=' . date('Y', $date) . ' AND month='
. date('m', $date)
);
$rows = $res->fetchAll();
$jobs = array();
foreach ($rows as $row) {
$job = new Job(/* $row['...'] */);
$job->rev = $job->time * $job->euro;
$jobs[] = $job;
}
return $jobs;
}
Теперь есть два абзаца. В первом есть ряд строк, выбранных из базы данных. Второй абзац преобразует эти строки в объекты. Это незначительное перемещение объявления $jobs
Это только верхушка айсберга, которую предлагает Чистый код.
Методология
Как видно выше, шаги рефакторинга действительно минималистичны — детские шаги . Это не только для целей презентации, но должно быть так, когда вы проводите рефакторинг. Рекомендуемый подход заключается в фиксации после каждого шага:
- Выберите 1 единственный шаг рефакторинга
- Выполнить выбранный шаг
- Убедитесь, что код все еще работает
- Зафиксировать текущее состояние и перейти к 1
Самое главное, эта процедура дает вам линию безопасности, чтобы вы могли легко отскочить на один шаг назад. Вы должны делать это всякий раз, когда чувствуете, что можете бежать в неправильном направлении. Если вам нужно начать отладку — не надо. Это слишком много усилий, чтобы попытаться исправить рефакторинг, а не отменить его. Хороши шансы, что вы потеряете свой путь в отладке, и это израсходует больше времени, чем начнется заново. Если вы идете с маленькими шагами, то возврат последнего шага займет 5 минут.
Кроме того, этот подход поможет вам оставаться сосредоточенным и непредубежденным в отношении конечной цели вашего рефакторинга. Код сложен, и наш мозг часто имеет предвзятое мнение о том, каков оптимальный результат этой сложной структуры. Сохраняя разум открытым для корректировки цели в процессе, вы позволяете ей находить лучшие решения на этом пути.
Процесс также позволяет вам прекратить рефакторинг в любой момент времени без потери прогресса. Срочную ошибку, чтобы исправить? Коллега просит спарринг? Обед? Нет проблем, вы можете либо просто объединить имеющееся у вас рабочее состояние, либо оставить его в ветке, чтобы потом снова поднять его.
Тем не менее, есть один недостаток с частыми коммитами во время рефакторинга: так много маленьких коммитов может загрязнить вашу историю контроля версий. Если вы используете Git, вы можете смягчить это, сгруппировав коммиты рефакторинга в один, перед тем как отправлять вверх по течению.
Предварительные условия
Принятие Чистого кода в качестве цели и применение шагов ребенка — хорошие строительные блоки для устойчивого рефакторинга, но есть еще что-то, что нужно принять во внимание.
Прежде всего, не стоит проводить рефакторинг только потому, что вы можете или потому что считаете, что текущий код выглядит некрасиво. Изменение кода — это всегда риск, и вы не должны рисковать без веской причины. Например, одной из причин может быть то, что вам часто приходится работать над одним фрагментом кода, который трудно понять и где каскадные изменения происходят в вашей системе. Но есть много других причин, таких как частые ошибки, непредвиденные бизнес-требования и т. Д. Важно тщательно проанализировать причины, а не просто слепо столкнуться с рефакторингом.
Во-вторых, важно иметь хотя бы некоторую степень автоматических тестов, охватывающих наиболее важные бизнес-случаи, когда используется рефакторинг кода. Устаревшие системы обычно сложно тестировать с помощью модульных или интеграционных методов тестирования. Поэтому рекомендуется не пытаться применять эти методы с помощью подхода грубой силы. Вместо этого мы сочли весьма полезным применять тесты через интерфейс — в нашем случае, используя Mink и PHPUnit.
Но, как и многие другие решения в разработке программного обеспечения, это только практические правила, и у каждого проекта есть свои требования и приоритеты. Присоединяйтесь ко мне на семинаре по чистому коду на WebSummerCamp 2016, чтобы узнать больше. Возьмите с собой компаньона — есть специальная программа для других значимых людей, так что приведите компанию и сделайте ее рабочим отпуском!