Решение о том, когда начать рефакторинг и когда остановиться, так же важно для рефакторинга, как и знание того, как управлять его механизмом.

Мы (Мартин Фаулер и Кент Бек) изучили множество кодов, написанных для проектов, которые охватывают диапазон от невероятно успешных до почти мертвых. При этом мы научились искать в коде определенные структуры, которые предполагают — иногда кричат ​​— о возможности рефакторинга.

Одна вещь, которую мы не будем пытаться дать вам, — это точные критерии того, когда рефакторинг просрочен. Что мы сделаем, так это покажем вам, что есть проблемы, которые можно решить с помощью рефакторинга. Вы можете не найти точный запах, который вы можете обнаружить, но, надеюсь, он укажет вам правильное направление.

Код Запахи

ЗАГАДОЧНОЕ ИМЯ

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

ДУБЛИРОВАННЫЙ КОД

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

ПЕТЛИ

Нам кажется, что сегодня они уже неактуальны. Мы обнаружили, что конвейерные операции, такие как фильтрация и сопоставление, помогают нам быстро увидеть элементы, включенные в обработку, и то, что с ними делается. Использование и злоупотребление первоклассными функциями.

ИЗМЕНЯЕМЫЕ ДАННЫЕ

Изменения данных часто могут привести к неожиданным последствиям и коварным ошибкам. Функциональное программирование основано на представлении о том, что данные никогда не должны изменяться и что обновление структуры данных всегда должно возвращать новую копию структуры с изменением, оставляя старые данные нетронутыми.

ДИВЕРГЕНТНОЕ ИЗМЕНЕНИЕ

Дивергентное изменение возникает, когда один модуль часто изменяется по-разному по разным причинам. Если вы посмотрите на модуль и скажете: «Ну, мне придется менять эти три функции каждый раз, когда я получаю новую базу данных; Мне приходится менять эти четыре функции каждый раз, когда появляется новый финансовый инструмент», — это признак расходящихся изменений.

ДЛИТЕЛЬНАЯ ФУНКЦИОНАЛЬНОСТЬ / БОЛЬШОЙ КЛАСС

Все, что вам нужно сделать, чтобы сократить функцию, в 99% случаев — это найти части функции, которые хорошо сочетаются друг с другом, и создать новую.

ДЛИННЫЙ СПИСОК ПАРАМЕТРОВ

Если вы можете получить один параметр, запросив для него другой параметр, вы можете заменить этот параметр запросом на удаление второго параметра.

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

СПЕКУЛЯТИВНАЯ ОБЩНОСТЬ

Вы понимаете, когда люди говорят: «О, я думаю, нам когда-нибудь понадобится возможность делать такие вещи» и, таким образом, добавляют всевозможные крючки и специальные случаи для обработки вещей, которые не требуются. Результат часто труднее понять и поддерживать.

Примечания. Для любопытства ссылки на шкалу Реомюра и шкалу Ренкина в Википедии

ГРУБКИ

Кучки данных, которые висят вместе, действительно должны найти общий дом. Хорошим тестом является удаление одного из значений данных. Если вы сделаете это, будут ли остальные иметь какой-либо смысл? Если они этого не делают, это верный признак того, что у вас есть объект, который умирает, чтобы родиться.

ДРОБОВАЯ ХИРУРГИЯ

Каждый раз, когда вы вносите изменения, вам приходится вносить множество мелких правок во множество разных классов. Когда изменения происходят повсюду, их трудно найти, и легко пропустить важное изменение.

ОСОБЕННОСТЬ ЗАВИСТИ

Feature Envy возникает, когда функция в одном модуле тратит больше времени на взаимодействие с функциями или данными внутри другого модуля, чем в своем собственном модуле. Мы потеряли счет тому, сколько раз мы видели, как функция вызывает какие-то методы-геттеры для другого объекта, чтобы вычислить какое-то значение.

ПРИМИТИВНАЯ Одержимость

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

ПОВТОРНЫЕ ПЕРЕКЛЮЧЕНИЯ (ИЛИ IFS)

Мы даже слышали, как некоторые утверждают, что вся условная логика должна быть заменена полиморфизмом, выбрасывая большинство «если» на свалку истории. Проблема с такими дублирующими переключателями заключается в том, что всякий раз, когда вы добавляете предложение, вам нужно найти все переключатели и обновить их. Против темных сил такого повторения полиморфизм представляет собой элегантное оружие для более цивилизованной кодовой базы. То же самое относится ко многим предложениям if/else.

ЛЕНИВЫЙ ЭЛЕМЕНТ

Иногда структура не нужна. Это может быть функция с тем же именем, что и ее основной код, или класс, который по сути представляет собой одну простую функцию. Это отражает функцию, которая, как ожидалось, будет расти и становиться популярной позже, но так и не осуществила свои мечты. Иногда это класс, который раньше окупался, но был сокращен в результате рефакторинга.

ВРЕМЕННОЕ ПОЛЕ

Иногда вы видите класс, в котором поле устанавливается только в определенных обстоятельствах. Такой код трудно понять, потому что вы ожидаете, что объекту потребуются все его поля. Попытка понять, почему существует поле, когда кажется, что оно не используется, может свести вас с ума.

ЦЕПОЧКИ СООБЩЕНИЙ

Вы видите цепочки сообщений, когда клиент запрашивает у одного объекта другой объект, который затем запрашивает еще один объект, который затем запрашивает еще один объект.

СРЕДНИЙ ЧЕЛОВЕК

Одной из главных особенностей объектов является инкапсуляция — сокрытие внутренних деталей от остального мира. Инкапсуляция часто сопровождается делегированием. Однако это может зайти слишком далеко. Вы смотрите на интерфейс класса и обнаруживаете, что половина методов делегируется этому другому классу.

ИНСАЙДЕРСКАЯ ТОРГОВЛЯ

Специалисты по программному обеспечению любят прочные стены между своими модулями и горько жалуются на то, что слишком большой обмен данными увеличивает связанность. Чтобы все заработало, должна происходить какая-то торговля, но нам нужно свести ее к минимуму и держать все в чистоте. Если модули имеют общие интересы, попробуйте создать третий модуль, чтобы сохранить эту общность в хорошо регулируемом транспортном средстве.

КОММЕНТАРИИ

Удивительно, как часто вы смотрите на густо закомментированный код и замечаете, что комментарии там потому, что код плохой. Хорошее время для использования комментария — это когда вы не знаете, что делать. Комментарий также может объяснить, почему вы что-то сделали.
Когда вы чувствуете необходимость написать комментарий, сначала попробуйте реорганизовать код, чтобы любой комментарий стал излишним.

Перейти к Главе 4 — Строительные тесты

Перейти назад к оглавлению