Refactoring Lecture Outline

Содержание

Слайд 2

Refactoring

Martin Fowler

Рефакторинг (сущ.)

Изменение во внутренней структуре программного обеспечения, имеющее целью облегчить понимание

Refactoring Martin Fowler Рефакторинг (сущ.) Изменение во внутренней структуре программного обеспечения, имеющее
его работы и упростить модификацию, не затрагивая наблюдаемого поведения

Рефакторинг (глаг.)

Процесс изменения структуры программного обеспечения путем применения рефакторингов

Refactoring: Improving the Design of Existing Code (1999)

“Improving the design after it has been written”

Слайд 3

Example

double PaymentAmount()
{
if ( quantity < 5 ) return 0;
if (

Example double PaymentAmount() { if ( quantity if ( months > 12
months > 12 ) return 0;
// compute amount
}

Каким код был

double PaymentAmount()
{
if ( NoPaymentNeeded() ) return 0;
// compute amount
}

Каким код стал

Слайд 4

Why Refactor?

Рефакторинг улучшает результаты проектирования ПО
- без рефакторинга структура проекта будет

Why Refactor? Рефакторинг улучшает результаты проектирования ПО - без рефакторинга структура проекта
ухудшаться, т.к. разработчики часто вносят изменения в сам проект
Рефакторинг облегчает понимание структуры ПО
- вследствие улучшения структуры проекта
Рефакторинг помогает найти ошибки
- рефакторинг способствует более глубокому вниканию в код
Рефакторинг позволяет быстрее писать программы
- вследствие всех вышеуказанных преимуществ

Слайд 5

When Refactor?

Правило «Трех страйков»
- если, минимум, в 3 местах
дублируется

When Refactor? Правило «Трех страйков» - если, минимум, в 3 местах дублируется
код, применяйте рефакторинг
При добавлении новой
функции
Когда необходимо
исправить ошибку
Во время Code Review
(анализ кода в команде)

Когда код слишком запутан (легче написать заново)
Когда код неработоспособен
Когда близится дата сдачи проекта

ПРИМЕНЯТЬ:

НЕ ПРИМЕНЯТЬ:

Слайд 6

Principles in Refactoring

Рефакторинг должен быть:
Систематичный
Поэтапный
Безопасный

Польза рефакторинга:
В большинстве случаев

Principles in Refactoring Рефакторинг должен быть: Систематичный Поэтапный Безопасный Польза рефакторинга: В
объем кода уменьшается
Запутанные структуры преобразуются в более простые (которые легче понимать и сопровождать)

Как надо проводить рефакторинг:
Не гнушаться паттернами рефакторинга (см. книги Фаулера)
Постоянное тестирование (в рамках концепции TestDrivenDevelopment - TDD)

Слайд 7

Problems with Refactoring

Рефакторить аспекты, связанные с БД, гораздо сложнее
Некоторые рефакторинги

Problems with Refactoring Рефакторить аспекты, связанные с БД, гораздо сложнее Некоторые рефакторинги
требуют серьезных
изменений интерфейсов
Некоторые изменения в проектировании сложно
поддаются рефакторингу

Слайд 8

Refactoring Vs. Optimization

Код меняется, а функциональность не меняется

При рефакторинге код становится

Refactoring Vs. Optimization Код меняется, а функциональность не меняется При рефакторинге код
понятнее; при оптимизации производительности – , в основном, гораздо сложнее для восприятия
При рефакторинге, в основном, код становится менее эффективным по памяти и по времени; при оптимизации – наоборот

ОБЩЕЕ:

ОТЛИЧИЯ:

Слайд 9

“Bad Smells” in Code

Дублирование кода (Duplicated Code)
Ситуации:
- один и тот же участок

“Bad Smells” in Code Дублирование кода (Duplicated Code) Ситуации: - один и
кода присутствует в 2 методах одного класса
- один и тот же участок кода встречается в 2 подклассах одного уровня
- дублирующийся код содержится в 2 разных классах
Длинный метод (Long Method)
Длинные методы затрудняют понимание кода. Соображениями о меньшей эффективности большого числа малых методов можно пренебречь

Слайд 10

“Bad Smells” in Code

Большой класс (Large Class)
Часто из-за больших классов увеличивается сцепление

“Bad Smells” in Code Большой класс (Large Class) Часто из-за больших классов
и уменьшается связность
Длинный список параметров (Long Parameter List)
Сложен для понимания
Расходящиеся модификации (Divergent Change)
Когда один тип изменений требует изменения одного подмножества частей класса, другой тип изменений – другого подмножества

Слайд 11

“Bad Smells” in Code

Стрельба дробью (Shotgun Surgery)
При выполнении любых модификаций приходится вносить

“Bad Smells” in Code Стрельба дробью (Shotgun Surgery) При выполнении любых модификаций
много мелких изменений во многих классах
Завистливые функции (Feature Envy)
Метод, который больше обрабатывает данные и вызывает функции чужого класса, чем родного
Группы данных (Data Clumps)
Часто встречающиеся и используемые связки данных, не являющиеся частью одного класса

Слайд 12

“Bad Smells” in Code

Одержимость элементарными типами (Primitive Obsession)
Избегание методики обертки данных в

“Bad Smells” in Code Одержимость элементарными типами (Primitive Obsession) Избегание методики обертки
классы
Операторы switch (Switch Statements)
Часто они дублируются в коде и часто могут быть заменены полиморфизмом
Параллельные иерархии наследования
(Parallel Inheritance Hierarchies)
Случай «стрельбы дробью» для классов, связанных отношением наследования. При внесении изменений в один подкласс, приходится вносить изменения во все подклассы параллельных иерархий

Слайд 13

“Bad Smells” in Code

Ленивый класс (Lazy Class)
Класс, существование которого уже не целесообразно

“Bad Smells” in Code Ленивый класс (Lazy Class) Класс, существование которого уже
(например, он в свое время нужен был, но после рефакторингов в нем отпала необходимость, или это класс, добавленный для планируемой модификации, которая не была произведена)
Теоретическая общность (Speculative Generality)
Возникает тогда, когда хотят обеспечить набор механизмов для работы с вещами, которые, возможно, будут нужны в будущем. Теоретическая общность может быть обнаружена, когда единственными пользователями метода или класса являются контрольные примеры (тесты)

Слайд 14

“Bad Smells” in Code

Временное поле (Temporary Field)
В некотором объекте свойство устанавливается /

“Bad Smells” in Code Временное поле (Temporary Field) В некотором объекте свойство
меняется только при некоторых обстоятельствах (типичный пример - вспомогательные переменные помещаются в свойства класса)
Цепочки сообщений (Message Chains)
Объект, делающий запрос, входящий в цепочку запросов к другим объектам, зависит от структуры навигации
Посредник (Middle Man)
Плохой признак, если класс делегирует слишком много своих действий другим классам (нужен ли он тогда сам вообще?)

Слайд 15

“Bad Smells” in Code

Неуместная близость (Inappropriate Intimacy)
Пара классов, которые слишком много знают

“Bad Smells” in Code Неуместная близость (Inappropriate Intimacy) Пара классов, которые слишком
и позволяют друг другу
Альтернативные классы с разными интерфейсами
(Alternative Classes with Different Interfaces)
Два или более метода классов делают практически одно и то же, но имеют разные сигнатуры
Неполнота библиотечного класса
(Incomplete Library Class)
Библиотечный класс не делает всего того, что Вам нужно

Слайд 16

“Bad Smells” in Code

Классы данных (Data Class)
Классы, которые содержат только свойства, геттеры

“Bad Smells” in Code Классы данных (Data Class) Классы, которые содержат только
и сеттеры для этих свойств, и ничего более (dumb data holders). Объекты должны отражать данные и обработку данных
Отказ от наследства (Refused Bequest)
Подкласс игнорирует большинство методов и данных родительского класса
Комментарии (Comments (!))
Излишние и некачественные комментарии. Комментарии иногда используются для сокрытия некачественного кода

Слайд 17

Refactorings

Реорганизация функций и данных

Составление методов
Перемещение функций между объектами
Реорганизация данных
Упрощение вызовов методов

Реорганизация условных

Refactorings Реорганизация функций и данных Составление методов Перемещение функций между объектами Реорганизация
выражений

Реорганизация обобщений

Слайд 18

Refactorings

Составление методов

Выделение метода
Встраивание метода
Встраивание временной переменной
Замена временной переменной вызовом метода
Введение поясняющей переменной
Расщепление

Refactorings Составление методов Выделение метода Встраивание метода Встраивание временной переменной Замена временной
временной переменной
Удаление присваиваний параметрам
Замена метода объектом методов
Замещение алгоритма

Слайд 19

Extract Method

Описание: Есть участок кода, который можно сгруппировать.
Действие: Поместить участок кода в

Extract Method Описание: Есть участок кода, который можно сгруппировать. Действие: Поместить участок
метод, название которого отвечает назначению.

Прием «Выделение метода»

Слайд 20

Extract Method (Example)

Extract Method (Example)

Слайд 21

Refactorings

Описание: Тело метода столь же понятно, как и его название.
Действие: Поместить тело

Refactorings Описание: Тело метода столь же понятно, как и его название. Действие:
метода в код, к-ый его вызывает, и удалить метод

Прием «Встраивание метода»

Слайд 22

Refactorings

Описание: Есть временная переменная, к-ой один раз присваивается простое выражение, и она

Refactorings Описание: Есть временная переменная, к-ой один раз присваивается простое выражение, и
мешает проведению «Выделения метода».
Действие: Заменить этим выражением все ссылки на данную переменную

Прием «Встраивание временной переменной»

Слайд 23

Refactorings

Описание: временная переменная используется для хранения значения выражения
Действие: преобразовать выражение в метод.

Refactorings Описание: временная переменная используется для хранения значения выражения Действие: преобразовать выражение
Заменить все ссылки на временную переменную вызовом метода. Новый метод может быть использован в других методах

Прием «Замена временной переменной вызовом метода»

Слайд 24

Refactorings

Описание: имеется сложное выражение
Действие: поместить результат выражения или его части во временную

Refactorings Описание: имеется сложное выражение Действие: поместить результат выражения или его части
переменную, имя которой поясняет его назначение

Прием «Введение поясняющей переменной»

Слайд 25

Refactorings

Описание: имеется временная переменная, которой неоднократно присваивается значение, но это не переменная

Refactorings Описание: имеется временная переменная, которой неоднократно присваивается значение, но это не
цикла и не для накопления результата
Действие: создать для каждого присваивания отдельную временную переменную

Прием «Расщепление временной переменной»

double temp = _width * _height;
cout << “Square: ” << temp;
temp = 2 * (_width + _height);
cout << “Perimeter: ” << temp;

До

double square = _width * _height;
cout << “Square: ” << square;
double perimeter = 2 * (_width + _height);
cout << “Perimeter: ” << perimeter;

После

Слайд 26

Refactorings

Описание: выполняется присваивание параметру
Действие: заменить это временной переменной

Прием «Удаление присваиваний параметрам»

double discount(

Refactorings Описание: выполняется присваивание параметру Действие: заменить это временной переменной Прием «Удаление
double price, int quantity ) {
if ( price > 1000.0 ) {
price *= 0.9;
}
if ( quantity >= 5 ) {
price *= 0.8;
}
return price;
}

До

double discount( double price, int quantity ) {
double result = price;
if ( price > 1000.0 ) {
result *= 0.9;
}
if ( quantity >= 5 ) {
result *= 0.8;
}
return result;
}

После

Слайд 27

Refactorings

Перемещение функций между объектами

Перемещение метода
Перемещение поля
Выделение класса
Встраивание класса
Сокрытие делегирования
Удаление посредника
Введение внешнего метода
Введение

Refactorings Перемещение функций между объектами Перемещение метода Перемещение поля Выделение класса Встраивание
локального расширения

Слайд 28

Refactorings

Описание: объект-клиент обращается к делегируемому классу объекта
Действие: создать на объекте-сервере методы, скрывающие

Refactorings Описание: объект-клиент обращается к делегируемому классу объекта Действие: создать на объекте-сервере
делегирование

Прием «Сокрытие делегирования»

class Person {
Department m_Dep; …
Department* GetDepartment() { … }
};
class Department {
Person* m_Manager; …
Person* GetManager() { … }
};
Person john; …
Person* manager =
john.GetDepartment().GetManager();

До

class Person {
Department m_Dep;
Person* GetManager() {
return m_Dep.GetManager();
}
};
class Department {
Person* m_Manager; …
};
Person john; …
Person* manager = john.GetManager();

После

Слайд 29

Refactorings

Реорганизация данных

Самоинкапсуляция поля
Замена значения объектом
Замена значения ссылкой (и наоборот)
Замена массива объектом
Дублирование видимых

Refactorings Реорганизация данных Самоинкапсуляция поля Замена значения объектом Замена значения ссылкой (и
данных
Замена однонаправленной связи на двунаправленную (и наоборот)
Замена магического числа символической константой
Инкапсуляция поля
Инкапсуляция коллекции

Слайд 30

Refactorings

Упрощение вызовов методов

Переименование метода
Добавление / удаление параметра
Разделение запроса и модификатора
Параметризация метода
Замена параметра

Refactorings Упрощение вызовов методов Переименование метода Добавление / удаление параметра Разделение запроса
явными методами
Замена параметра вызовом метода
Введение объекта параметров
Удаление сеттера
Сокрытие метода

Слайд 31

Refactorings

Описание: Несколько методов выполняют сходные действия, но с разными значениями, содержащимися в

Refactorings Описание: Несколько методов выполняют сходные действия, но с разными значениями, содержащимися
теле метода
Действие: Создать один метод, к-ый использует для задания разных значений параметр

Прием «Параметризация метода»

void DiscountForMen()
{…}
void DiscountForWomen()
{…}

До

void Discount( char cSex )
{

}

После

Слайд 32

Refactorings

Реорганизация условных выражений

Декомпозиция условного оператора
Консолидация условного выражения
Консолидация дублирующихся условных фрагментов
Удаление управляющего флага
Замена

Refactorings Реорганизация условных выражений Декомпозиция условного оператора Консолидация условного выражения Консолидация дублирующихся
вложенных условных операторов граничным оператором
Замена условного оператора полиморфизмом
Введение объекта NULL

Слайд 33

Refactorings

Описание: имеется сложная условная цепочка проверок
Действие: выделить методы из условия, блоков THEN

Refactorings Описание: имеется сложная условная цепочка проверок Действие: выделить методы из условия,
и ELSE

Прием «Декомпозиция условного оператора»

Слайд 34

Refactorings

Описание: имеется ряд проверок условия, дающих одинаковый результат
Действие: объединить их в одно

Refactorings Описание: имеется ряд проверок условия, дающих одинаковый результат Действие: объединить их
условное выражение и выделить его

Прием «Консолидация условного выражения»

Слайд 35

Refactorings

Описание: один и тот же фрагмент кода присутствует во всех ветвях условного

Refactorings Описание: один и тот же фрагмент кода присутствует во всех ветвях
выражения
Действие: переместить его за пределы условного выражения

Прием «Консолидация дублирующихся условных фрагментов»


if ( IsSpecialDeal() )
{
total = price * 0.8;
Send();
}
Else
{
total = price * 0.9;
Send();
}

До


if ( IsSpecialDeal() )
{
total = price * 0.8;
}
Else
{
total = price * 0.9;
}
Send();

После

Слайд 36

Refactorings

Описание: имеется переменная-флаг
Действие: использовать вместо нее break или return

Прием «Удаление управляющего флага»

Refactorings Описание: имеется переменная-флаг Действие: использовать вместо нее break или return Прием «Удаление управляющего флага»

Слайд 37

Refactorings

Реорганизация обобщений

Подъем поля / Подъем метода
Спуск поля / Спуск метода
Выделение подкласса
Выделение родительского

Refactorings Реорганизация обобщений Подъем поля / Подъем метода Спуск поля / Спуск
класса
Выделение интерфейса
Свертывание иерархии
Формирование шаблона метода
Замена наследования делегированием и наоборот

Слайд 38

Refactorings

Описание: в подклассах есть методы с одинаковыми результатами
Действие: переместить их в родительский

Refactorings Описание: в подклассах есть методы с одинаковыми результатами Действие: переместить их
класс

Прием «Подъем метода»

Имя файла: Refactoring-Lecture-Outline-.pptx
Количество просмотров: 151
Количество скачиваний: 0