Refactoring

Материал из AgileWiki

Перейти к: навигация, поиск

Содержание

Refactoring

Приемы и принципы улучшения читабельности кода, как следствия уменьшения его стоимости. Является составной частью цикла разработки: тест -> код -> рефакторнг, но может использоваться и в упращённой схеме: изменения -> рефакторинг или рефакторинг -> изменения -> рефакторинг (Денис Миллер).

Статьи

Рефакторинг: 7 вариантов убеждения заказчика

Пока я собираю материал и обдумываю аргументы для второй статьи по теме «Scrum без...» встретился с необходимостью убедить заказчика в необходимости отдельной сессии рефакторинга.

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

1.В начале работы мы должны в общих чертах продумать архитектуру

2.Пока пишем код пишем и юнит-тесты

3.Как только встречаем что-то, что написано не красиво или просто не получается сделать в рамках текущей архитектуры — сразу рефакторим: при наличии юнит-тестов проблем возникнуть не должно.

Но, если вы все-таки практикуете Scrum и, к тому же, живете в той же реальности, что и я могут возникнуть следующие проблемы:

1.Основная идея проекта, на которую была рассчитана ваша архитектура изменилась и теперь всякое изменение дается с трудом. Пример: сначала хотим очень гибкую систему, которая могла бы служить единой платформой для всех заказчиков. Со временем понимаем, что пожелания этих заказчиков настолько различны, что нет никакого смысла пытаться делать эту самую единую систему и куда проще (Keep It Simple Stupid — KISS) для каждого из заказчиков сделать отдельную систему.

2.Со вторым пунктом все ясно: хоть в теории только команда и может ставить сроки, на практике кроме команды есть еще куча людей, которые прямо-таки рвутся установить свои сроки, причем еще ни разу не встречал, чтобы настаивали на сроках бОльших, чем говорит команда. Обычно наоборот. Если у вас в компании есть хоть один сейлз вы 100% встречались с такой ситуацией, хотя, допускаю, что вы смогли отмахаться :) И хоть в теории мы и не должны жертвовать качеством, на практике и карьерой не хочется жертвовать, а потому из двух зол выбираем меньшее — отказываемся от юнит-тестов.

3.Этот пункт тоже связан с нехваткой времени. Поставлю золотой памятник тому, кто расскажет как в 100% случаях убедить заказчика отложить релиз. А если уже запустили рекламу или заказчики уже договорились с субподрядчиками? И если та задача, которую вы ну никак не успеваете сделать, нужна кровь из носу и без нее проект никому вообще не нужен? Какие тут варианты, кроме как кроме юнит-тестов начать жертвовать и качеством (злорадно предупредив заказчика, что ничего путного из этого не выйдет). Одного из пунктов в принципе достаточно для того, чтобы код превратился в длинные полоски вермишели, понятия перемешались и чтобы в коде появилось множества комментариев типа:

1.// Костыль

2.// Hardcode :(

3.// Пусть пока будет так — потом исправлю ;)

И с каждым таким комментарием растет цена на внесение изменений, что, рано или поздно заметит заказчик. Например, когда реализация истории по созданию странички FAQ по вашим оценкам займет половину всего времени, отведенного на спринт просто потому, что ваша CMS держится на честном слове и 80% времени уйдет на то, чтобы все перетестировать.

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

Уверен, что в 90% случаев у product owner'а (или у его босса или у босса его босса :)) возникнет вопрос: зачем тратить неделю [хотя бы]работы команды на что-то под названием рефакторинг, если «... и так все работает».

В этой статье мы поговорим как раз о бизнес-обоснованиях сессии рефакторинга. Оговорюсь, что задача не только в необходимости убеждения product owner'а в том, что такая сессия необходима, но и в том, что не должно быть работы просто ради работы — все должно приносить бизнес-value. Это тот самый критерий, по которому команда должна отбирать идеи для рефакторинга. В любой задаче, даже в задаче по рефакторингу системы, должно быть business-value. Если business value есть — задачу можно рассматривать для включения в сессию рефакторинга, если его нет — тогда и смысла в этом немного, и заказчика будет сложно убедить. Итак, 7 вариантов обоснования необходимости рефакторинга:

Вариант №1: уменьшение стоимости внесения изменений

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

1.Вряд ли стоит рассматривать эту идею, если не предполагается никаких изменений в той части, которую вы хотите рефакторить.

2.Всегда нужно примерно сравнивать стоимость самих работ по рефакторингу и вероятность и частоту внесения изменений в ту область, с которой вы планируете работать. Если рефакторинг займет 5 человеко-недель, а за все время разработки проекта изменения в эту часть вносились лишь один раз... в общем вы поняли :) И да — в идеале всеми этими просчетами должен заниматься заказчик, но вы облегчите ему и себе жизнь, если сами подумаете об этом перед тем, как вызывать заказчика на 2-х дневное совещание для обсуждения 257 идей для рефакторинга.

Вариант №2: поддержка новой функциональности

Одним из основных принципов Scrum и Agile вообще в том, что сам заказчик никогда не может знать все, что ему нужно на самом деле. Например, он может попросить вас реализовать «простую систему отчетности», а к концу проекта (мы говорим про после_авральную фазу, помните? Жертвовать качеством можно только в том случае, если альтернативой являются только потеря рабочего места или заказчика) выяснится, что простая она для него, а вы таких графиков и в глаза никогда не видели, и даже предположить не могли, что такие вообще бывают. А потому, оглянувшись назад и заглянув вперед вы можете обнаружить, что рефакторинг системы отчетности даст вам, кроме всего прочего, возможность легко добавлять новые типы графиков. По-моему мнению, если задача по рефакторингу попадает под это условие ее нужно делать в 90 случаях из 100. Особенно если вы уверены, что эта новая функциональность рано или поздно появится.

Вариант №3: оптимизация системы

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

Вариант №4: создание возможности для автоматизации

Долго пытался сформулировать понятно и тем не менее не уверен, что получилось :) А потому объясню. Этот вариант можно рассматривать как симбиоз вариантв «поддержка новой функциональности» и «уменьшение стоимости внесения изменений». Под этот вариант могут подойти все изменения, связанные с вынесением отдельных параметров в конфигурацию, реализация поддержки собственных простеньких скриптов или XML для описания последовательностей, правил и т.п. как альтернатива жесткому хардкоду. Например, если у вас есть набор правил, по которому рассчитывается дата рассылки почты, то, возможно, имеет смысл реализовать более гибкий механизм, который позволил бы вам легко добавлять и изменять правила, а может даже позволил бы делать это самому заказчику. Они хоть и очень заняты, но часто любят собственноручно поучаствовать в работе. В качестве еще одного примера можно привести реализацию описания отчетов с помощью XML с тем, чтобы позже можно было позволить заказчикам самим составлять отчеты через пользовательский интерфейс.

Вариант №5: вынесение общих частей систем в отдельную подсистему

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

Вариант №6: улучшение пользовательского интерфейса

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

Вариант №7: переход на новую технологию/версию

В случае желания перейти на новую технологию или новую версию этой же технологию всегда нужно задаться двумя вопросами:

1.Что команду не устраивает в данной версии и не проявится ли это что-то и после изменения

2.Какие проблемы сулит собственно переход

Эти вопросы помогут выяснить необходимость перехода со стороны команды, но, что более важно, должно быть что-то, что будет иметь ценность для клиента. Вот только несколько вариантов:

1.Безопаснее. Например, использовать последнюю версию нужно потому, что в старой найдены критические уязвимости. В наш век, когда существует понятие «вечной бета-версии» (практически все продукты Google, например), это может оказаться серьезным доводом

2.Быстрее. Редкий релиз новой версии не сопровождается словами «теперь это работает в N раз быстрее». Это связано с вариантом «оптимизация системы»

3.Возможность использовать функционал, который отсутствует в текущей версии/технологии. Что важно — этот функционал должен быть востребован в первую очередь заказчиком. Под это подходят все перечисленные выше и ниже варианты Как и все статьи на этом блоге, эта статья не претендует ни на энциклопедичность, ни на полноту изложения, ни на работоспособность во всех возможных случаях. Все эти варианты использовались мной в личной практике (правда, слава Богу не для того, чтобы аргументировать product owner'у необходимость рефакторинга, а для убеждения боса боса product owner'а :)) и все имели ценность для моей команды и для моего заказчика.А потому, если у вас есть вопросы, мнения, критика и пр. прошу высказываться в комментариях!

Ссылки

Личные инструменты