Lumber room
July 2009 20

Рефакторинг: миссия (не)выполнима?

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

А как делать этот самый рефакторинг, если даже неизвестно, с чего начать? Как осушить болото кода и не утонуть нем?

Конечно, идеальный вариант — считать рефакторинг одной из активности на проекте с самого его начала и выделять на него проектное время команды. В жизни, как ни странно, однако чаще всего оказывается, что предыдущий лид проекта не сильно озадачивался этим вопросом, предпочитая плыть по течению; возможно, он надеялся когда-нибудь сбагрить эту ношу менее удачливому лиду — пока проект еще не развалился; а может быть, просто не знал, что делать. Шеф, усё пропало!

Расскажу, как делаю я.

Правило номер 1: рефакторинг — это процесс. Поэтому, прежде всего, нужно сдружиться с мыслью, что переделать на «зашибись» не получится ни через неделю, ни через две. После осознания этого факта берем книгу М.Физерса, «Эффективная работа с унаследованным кодом» (Working Effectively With Legacy Code), и начинаем с ней знакомиться. Одновременно удостоверяемся, что хорошо освоились с source control, который у нас используется, и параллельно чтению книги приводим в порядок код (первичная «зачистка»): удаляем закомментированный и «мертвый» код, ему не место в проекте; структурируем «кашу» по файлам; привОдим в соответствие сoding convention. Более серьезных переделок на этом этапе лучше не проводить. Если есть возможность писать юнит-тесты — следует над этим подумать (но не делать, так как обычно на этом этапе писать их пока бесполезно, давайте терпеть до следующего :).

Правило номер 2: source control всему голова. Вы будете смеяться, если узнаете, как много людей не знаю, что такое бранч. Хорошее знание source control поможет не похерить окончательно проект в случае, если некоторые из ваших многочисленных изменений «несовместимы с жизнью». В такой ситуации только rollback спасет отца русской демократии. Собсна, я рекомендую известный труд SvnBook тыц, особенно по части бранчей, даже если у вас не svn. Также можно поискать в сети слайды Source control & Agile и тыц. Очень весело про source control написано тут.

Правило номер 3: автоматизируйте рутину, это примета — к счатью :) Это я к тому, что стоит обзавестить какой-нибудь системой автобилда, чтобы собрать проект можно было в 1 клик. Такая система — реально плюс к морали, потому что я не раз встречался с ситуацией, когда проект нужно было строить руками из студии, полчаса копируя артефакты в сложной последовательности по странным расшаренным папкам в сети, и такая ситуация очень сильно отбивала у людей охоту что-то менять. Я долгое время пользовался CruiseControl (рекомендую), счас используется TeamBuild из TFS (политика партии), но непринципиально — для начала сойдет и make/ant/nant, запускаемый из консоли.

К тому моменту, как книгу дочиталась, codebase должна выглядеть прилично, чтобы, по крайней мере, не тошнило от исходников, а также легко пересобираться. Конечно, до ощущения красоты проекта еще ой как далеко, да и архитектура не то чтобы хромает — еле ходит :)

Правило номер 4: начинаейте с малого, но хорошего. А именно: дальнейшая стратегия работы с проектом следующая: для той части проекта, над которой мы работаем счас, выделяем «песочницу», в которой все будет «как надо» — изолируем ее от остальной части кода, пишем ее _хорошо_ — ООП, best practices в руки. Весьма желательны юнит-тесты. Весьма — потому что делать рефакторинг на меткий глаз и честное слово лучше вообще никогда :)

По мере написания своего кода станет ясно, что нашей подсистеме так или иначе придется обращаться к остальному коду некоторым способом. Эту поверхность взаимодействия выделяем в отдельный API (для .net, например, я создаю статический класс, через методы которого мой код взаимодействует со старым) и также пишем unit-testы для него. Как именно его сделаеть и насколько аккуратно — это непринципиально, потому что мы от него постепенно избавимся. После того, как наш «красивый» код успешно работает с этим API, и есть тесты для этого API, можете заглянуть за него, и рефакторить существующее за ним «мясо» согласно книге, которую вы прочли, продолжая покрывать тестами вглубь. В книге, на которую я сослался, также описаны приемы, которые могут помочь, если вы не начинаете с собственной песочницы, а дополняете функционалом существующий (плохо)код.
В общем, отсюда плавно истекает (болото же ж, как-никак!) правило 5: работает — не трогай, а напиши юнит-тест, потом ломай. И то — если наш код туда как-то лезет.

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

Чуть не забыл — на каждом этапе вашего долгого (не сомневайтесь;) пути вам могут быть полезны инструменты автоматического анализа кода — (Visual)NDepend, FxCop и Gendarme для .net/mono, simian, всякие line counters и прочие (lint, например, если вы С/С++). Java-, php- и остальные товарищи могут вписать требуемое.

Кажется, все.
В комментариях хотелось бы увидеть ваши способы заруливания «быдлокода» путем рефакторинга — нечего прятать полезную информацию.
+63
897 90
Comments 52