XP Days Ukraine 2014 - Refactoring legacy code

Preview:

Citation preview

Refactoring Legacy Code

Дмитрий Миндра

SDET, Unity Technologies (Ciklum)

@dmytromindra

О докладчике

2010 - Lohika

2012 - Microsoft

2013 - Unity Technologies

Когда-то был приличным

инженером, но 10 лет назад

связался с дотнетчиками,

выучил C#, занялся ООП,

скатился к TDD и

модульному тестированию.

Характер скверный.

Женат

Extreme Programming (XP)

SCRUM ЭРА

Что такое legacy code?

1. Это код без тестов

2. Код без спецификации

3. Код написанный очень давно и

неизвестно кем.

4. …

MakeFlagWavingBastardWaveHisFlagWhichIsTheProbablyTheLastThingHeWillEverDo()

Найдено в Carmageddon 1 debugging symbols dumped

Как появляется Legacy Code?

Как появляется legacy code?

• Гонка за фичами (нужно больше золота)

• Меняющиеся требования.

• Костыли и хаки.

• Ротация разработчиков.

• Отсутствие мыслей о завтрашнем дне (

сопровождении кода )

Золотое правило

• Работает – не трогай!

Зачем мы меняем код ?

• Нужно добавить фичу.

• Нужно пофиксить баг.

• Нужно улучшить производительность.

ВАЖНО!

• Legacy код – это всегда работающий

код, задействованный в

функционировании программной

системы.

Что делать?

• Переписать заново (как правило плохая

мысль)

• Найти новую работу …

• Сделать код «не legacy» кодом.

Учись, иначе т

Учись, студент! Иначе, всю

жизнь вот так будешь

только ключи подавать!

Самая популярная техника

работы с Legacy Code

Edit and pray

С чего начать ?

• Определить что именно нужно менять

• Определить какие тесты нужны

• Запустить и проверить

• Написать тесты

• Внести изменения

С чего начать ?

• Определить что именно нужно менять

– Старый код бывает очень сложно понять

– Изменения могут быть сильно

распределены по коду

• Определить какие тесты нужны

• Запустить и проверить

• Написать тесты

• Внести изменения

С чего начать ?

• Определить что именно нужно менять

• Определить какие тесты нужны– Мы хотим убедиться, что код работает так же,

как работал до вмешательства.

– Есть ли механизм для мониторинга результатов.

– Мы не боимся долгих и сложных тестов на этом этапе!

• Запустить и проверить

• Написать тесты

• Внести изменения

Approval Tests

1. Сериализуем результат в текст

2. Сравниваем с эталоном

http://approvaltests.sourceforge.net

С чего начать ?

• Определить что именно нужно менять

• Определить какие тесты нужны

• Запустить и проверить

– Можем ли мы создать класс/вызвать метод в тесте?

– Можем ли мы получить результат вычислений?

• Написать тесты

• Внести изменения

Seams

• Швы – места, позволяющие менять

поведение программы не меняя код в

этом самом месте.

• Швы бывают объектные и линковочные

Sensing and Separation

• Sensing – мы меняем код для того,

чтобы получить доступ к результатам

вычислений.

• Separation – мы меняем код для того,

чтобы получить создать класс или

вызвать метод внутри теста.

Separation

В данном случае мы будем бороться за право создать экземпляр.

Самый простой рефакторинг – это добавить конструктор по умолчанию.

Separation

Старый код часто нарушает принцип DI

Избавляемся от зависимости

• Пожалуй самая распространенная

техника – Extract Interface &

Parameterize Constructor.

Extract Interface

Сначала избавимся от очень общего названия Sensor

Затем извлечем интерфейс Sensor

Parameterize Constructor

Конструктор по умолчанию все еще создает зависимость,

но теперь есть возможность подменить ее в тесте.

Extract and Override (шаг 1)

Было:

Стало:

Factory Method

Extract and Override (шаг 2)Factory Method

Почему Extract and Override?

• Legacy code – это зона риска. Мы

стараемся менять его минимальными

безопасными шагами (baby steps).

Шаг 1: Добавить метод

Шаг 1: Добавить методПопробуем обернуть вызов source.Read() методом Modify()

Это безопасная операция с минимальной модификацией

кода.

Шаг 2: Перегрузить его

Безопасно ли поменять private на protected? Вполне!

Безопасно ли сделать метод virtual? Вполне!

Теперь мы можем переопределить это поведение в

наследнике операцией, не меняющей исходный код

тестируемого класса.

Шаг 2: Перегрузить его

Extract and Override3rd party

Ох уж эти 3rd party, которые так сложно тестировать.

Extract

Override

Sensing with Extract and Override

С чего начать ?

• Определить что именно нужно менять

• Определить какие тесты нужны

• Запустить и проверить

• Написать тесты

– Эти тесты больше похожи на приемочные тесты.

– Они могут быть медленными, могут обращаться к внешним сервисам и базам данных

– Главная цель этих тестов определить работает ли старый код так же, как работал до вмешательства.

• Внести изменения

С чего начать ?

• Определить что именно нужно менять

• Определить какие тесты нужны

• Запустить и проверить

• Написать тесты

• Внести изменения и выполнить настоящий рефакторинг

– Когда код покрыт тестами он уже формально не является легаси кодом.

– Его можно рефакторить и править.

Вопросы

?

Что почитать?

Michael C. Feathers “Working Effectively

With Legacy Code”

Упражнение

https://github.com/DmytroMindra/GildedRos

e

Recommended