×Закрыть

Рефакторинг, как его не бояться

Тезисы и выдержки из лекции о рефакторинге

Кому необходим рефакторинг?

Рефакторинг необходим и вам и заказчику: для вас он экономит время, для заказчика — деньги.

Когда необходим рефакторинг?

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

Что для этого нужно?

Не ссать. Не боятся что-то менять в проекте, для этого необходимо быть на 100% уверенным в результате своих действий, и в этом вам помогут юнит тесты или медитации на свежем воздухе :)

С чего начинать рефакторинг проекта?

1. Анализ существующей системы


— Я перепишу этот код за неделю!!!
— А поточнее?
— Мне понадобится не больше, чем 340 часов.
— О_о

Подобный диалог не плод моей фантазии, так что перед тем как что-то делать необходимо провести анализ кода, и сделать небольшой отчет — что в проекте сделано плохо, что хорошо, а за что стоит сломать кому-то руку или даже две. Акцентируйте внимание на критичных местах для проекта и для разработчика (два десятка пунктов, не меньше), система оценки от −5 до +5, где −5 обозначает — «за нас сделали часть работы, и сэкономили нам время», а +5 — «нам тут насыпали кучу, придется ее разгребать»:


Что мы нашли И как оно
Не используется система контроля версий +5
Структура БД прозрачна, и понятна без описания -4
Используются нативный доступ к БД без врапера +4
Фреймворк не используется +2
Нет единой точки входа +1
Нет разделения логики и отображения +5
Много неиспользуемого кода +2
Хардкод того, что должно быть в конфиге +1
Комментарии в коде на испанском языке +3
Нет единого стиля кодирования +1
Десяток сторонних библиотек сомнительного качества и устаревших версий +4
Куча правил в .htaccess +3
Невалидный HTML4 +2
Табличная верстка с множеством вложенных таблиц +3
Около десятка подключаемых CSS +3
Используются <img> как элементы дизайна +3
Используется jQuery -3
Используется jQuery UI -3
Используются старые версию JS фреймворков +2
Используется еще и prototype.js +4
Итого 38

В сумме у нас получается 38 баллов, это значит, что рефакторинг нам необходим как воздух:

от −100 до −10 рефакторим проект по мере разработки нового функционала
от −10 до 10стоит выделить самые критичные моменты и заняться ими отдельно, пока они не стали больной мозолью
от 10 до 50необходимо составить план рефакторинга, и не затягивать с реализацией
от 50 до 100вначале рефакторинг, после — функционал

2. Оценка трудозатрат

Не распыляемся на мелочи, если стиль кодирования фиксится двумя кликами в IDE то не стоит его лишний раз упоминать, нам же нужно мясо:

Что делаем Сколько стоит (ч/ч) Эффект
Враппер для БД 40 Экономит наше время
Проверка и установка индексов для БД 10 Ускоряет сайт в 10 раз
Кеш для запросов 40 Ускоряет сайт в 2 раза
Разделение логики и отображения 40 Ускоряет разработку
Кеш для шаблонизатора 20 Ускоряет сайт в 10 раз для незалогиненых пользователей

Данная оценка является фактически нашим планом по рефакторингу проекта, так чего же мы ждем?

3. Продажа рефакторинга

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

  1. Заказчик — вменяем и, возможно, не далек от IT
  2. Заказчик — слишком близорукий и скряга

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

Что делаем Сколько стоит Эффект
Magic 150 Ускоряет сайт в 20+ раз

4. Оптимизация

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

Сайт Время отдачи HTML DOM Ready Время загрузки страницы
facebook.com ~0.3 ~0.4 ~2
yahoo.com ~0.7 >3 >6
twitter.com ~0.7 >4 >5
amazon.com ~0.3 >2 >5
ebay.com ~0.7 >1 >2
digg.com 1 ~2 >4

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

  1. Сервера не справляются с нагрузкой
  2. Генерация страницы занимает >1 сек

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

5. Приемный ребенок

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

Вместо вывода

Что бы вы не делали в проекте, ваша работа не должна усложнять дальнейшую разработку и поддержку проекта, но не стоит зацикливаться на «идеальности» кода, всегда нужно знать меру.

LinkedIn

21 комментарий

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

Фреймворк не используется +2

О! Я бы поставил −5 :-)))) Потому что в случае «фреймворк используется», то это «нам тут насыпали кучу, придется ее разгребать» (но это спорно, потому что личностное).

Используется jQuery -3

Разве jQuery не разновидность фреймворка? Значит таки какой-то используется. Но это один из немногих реально полезных.

Основная цель рефакторинга является сделать код более понимаемым человеку. Улучшение производительности и улучшение расширяемости проекта является приятным бонусом.

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

Несколько отвлеченный и, возможно, провокационный коммент из точки «где-то между маркетингом (заказчиком) и разработкой».

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

В стартаперских проектах очень часто встречаются ситуации, когда нужна серия «production-ready prototypes». Звучит на первый взгляд дико, со стороны разработчика выглядит как некомпетентность заказчика («сам не знает, чего он хочет, только мозги пудрит»), а суть, между тем, предельно проста — маркетинг тоже не по RUPу работает и соответственно нуждается в экспериментах (ломая архитектуры и идеи на корню), причем в катастрофически сжатые сроки. И таки да, пока еще не знает, чего он хочет. В точности как наше «Мы тут попробуем клевую фишку, 100% съекономим, думаю, за 3 дня напишем» (в последующим криком о пролетевших на 3 недели уже сроках).

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

Знакомо?

Им просто нужно проверить прототип. Не сервера, не приложения, а бизнес модели. Например, работающее «нечто», которое начинает уже сейчас привлекать клиентов (даже на шару) может означать, что модель таки работает и теперь уже можно вкладываться в разработку по-настоящему, и потерянный человеко-год (все эти наколенки и PoC в продакшне) — на самом деле капля в море расходов. И понятие эффективности вложений денег не всегда равно сумме выплаченой ЗП + накладные расходы.

Так что, часто (ИМХО заметно более половины случаев), имеет место быть необходимость сделать «таки быстро и грязно на коленке», зная, что все эти человеко-года овертаймов в результате будут выброшены по нескольку раз, со сменой языков и операционок, переползая по дороге с кластера в сотню Core i7 на мобильный Cortex A8 и обратно.

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

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

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

Одним из требований предъявляемых к рефакторингу является проведение оптимизации системы

Это самая частая ошибка тех, кто начинает рефакторинг — начинает меняться функцонал и происходить оптимизация чего-либо. Не делайте этого! И тем более не стоит делать какие либо замеры производительности на этапе рефакторинга — можно не выкарабкаться :)

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

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

И продавать рефакторинг под видом магического результата — не стоит.Исходя из личного опыта, в условиях средне-плотной загруженности по проекту, на рефакторинг можно смело выделять час-полтора в день, даже без уведомления клиента (достаточно тех-лида, понимающего зачем ЕМУ, а никак не клиенту, это нужно).

Ускоряет сайт в 20+ раз

рефакторинг с таким девизом да — чреват фейлом.

мухи и котлеты — гремучая смесь.

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

3. Хорошо, если есть возможность работать, это по баллам <10, но когда каждый шаг делать все тяжелей и тяжелей — то тут надо требовать с заказчика время на проведение рефакторинга, иначе час в день не спасут ситуацию.

1. Рефакторинг с точки зрения заказчика (она же краткосроная перспектива продукта) — это как раз и есть «топтание» на месте. Это сродни планированию архитектуры — она тоже топтание на месте в краткосрочных показателях.

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

3. Если нет возможности выкроить час времени в день на рефакторинг, — значит что-то у вас не так в построении процесса. Не верю!
Небось на тупое клонирование очередного шаблона методом Copy&Paste время есть.
В крайнем случае попросите ваших программистов остаться раз на пару часов дольше и под пиво, пиццу, музыку, шутки сделайте хотя бы начните процесс. Если представить это как fun, а не как колупание в Г по самые локти — то разработчик этим загорится, и в дальнейшем доведет начатое самостоятельно.

терминологический спор.

почему это рефакторинг это изменение кода, но не изменение архитектуры системы?

для меня всё, что не меняет функционал — рефакторинг. И Фаулер согласен: «Refactoring is the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure.» :)

если я выделяю модели, вьюхи и контроллеры из общей кучи кода — я меняю архитектуру? а если вношу слой доступа к БД? заменяю SQL на какой-нить ОРМ?

=="Refactoring is the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure." :)
если я выделяю модели, вьюхи и контроллеры из общей кучи кода — я меняю архитектуру? а если вношу слой доступа к БД?== до этого момента всё правильно, а здесь — стоп :

заменяю SQL на какой-нить ОРМ?

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

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

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

1. Согласен

2. Контр-пример. Замена метода с алгоритмом O(n^2) на аналогичный метод с O(n) является рефаткорингом, который при этом може существенно повлиять на производительность. При том, что оба метода работают с точки зрения вызывающего кода без ошибок.

3. Противоречиво. Рефакторинг долже быть частью процесса. Для меня fun — писать классный код, но и быть с моей семьей. Не стоит призывать людей отказываться от второго ради первого. :-)

годная статья. просто о нужном.

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

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

наверно, лучше относиться к проекту как повар к картошке.

Рефакторинг как повод помедитировать на свежем воздухе :)

Рефакторинг не нужен, если:
1. Проект работает, ничего нового не пишется
2. Новый функционал не требует переписывания/изменения старого
3. Юнит тесты отсутсвуют как вид
4. Вы неуверены, что сделаете лучше

5. Код не поддается рефакторингу

4. Вы не уверены, что сделаете лучше -> та ну... причесать код — как в квартире прибрать, неохота, но надо.

5. Код не поддается рефакторингу -> это как? невозможно понять смысл кода и написать джавадоки к методам? декомпозицию класса МухиИ_Котлеты невозможно провести?

Случаи 4 и 5 можно встретить почти в любой IT фирме, не вижу смысла приводить примеры.
Все когда то с чего то начинали.

3. Юнит тесты отсутсвуют как вид

это тоже причина\повод отказаться от рефакторинга?

Из двух десятках проектов (большинство из которых были успешными) только в нескольких у нас были юнит-тесты. Ни разу отсутвие юнит-тестов не мешало рефакторингу.

Более того, отказ от рефакторинга для меня сродни приговору проекту. Код либо ушел в релиз, либо мертв, если не меняется.

Ага — в кои-то веки отсутствие перчаток мешало лезть в трансформаторную будку :) Не правда-ли что-то напоминает?

Давайте порефакторим, а баги внесенные по ходу дела — то такое уже...

Не путайте народ! Без юнит-тестов рефакторинг кончно затея не лучшая — однако делать можно если очень осторожно. Куда безопаснее и спокойнее делать рефакторинг при наличии юнит-тестов. Т.е. я к тому если нет юнит-тестов, то это вовсе не означает что рефакторинг делать не нужно, нужно написать юнит-тесты и следом за ними приступить к рефакторингу. Код не может не поддаваться рефакторингу, это вопрос квалификации. И даже если проект работает и ничего нового не пишется, то очень полезно проводить ревизию кода и если требуется рефакторинг. Как минимум это будет полезно как самому проекту для поддержки кода в хорошем состоянии, так и тому кто затеял рефакторинг как тренировка для мозгов. Ну и для меня лично это всегда приятная и интересная процедура, творческий процесс.

3. Юнит тесты отсутсвуют как вид

Гы :) А здесь всё просто. Рефакторинг начинается с написания юнит-тестов для старой системы.

Подписаться на комментарии