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

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

Ошибка №1. Переписывать с нуля сразу весь сервис

Да, это очень привлекательный и самый очевидный вариант. Зачем тратить время и ресурсы на поддержку legacy сервиса и интеграцию нового в старое, если можно сразу написать новый код, а потом перевезти сервис на него? Это же гораздо эффективнее! К тому же, новая архитектура совсем не совместима со старой.

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

Как избежать

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

Ошибка №2. Начинать переписывать продукт как только вы пришли в компанию

Итак, вы начали работать над новым продуктом месяц назад, и видите, что архитектура сервиса никуда не годится. Знакомо? У вас, само собой, возникает желание переделать все с нуля, ведь поддерживать такой продукт очень сложно.

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

Как избежать

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

Ошибка №3. Думать, что новый язык или фреймворк решит все проблемы

Раз уж мы решили переписывать сервис — нужно использовать самые современные инструменты. А тут как раз вышел новый мега-крутой фреймворк, где много классных возможностей, которые отлично впишутся в наш продукт. 

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

Как избежать

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

Ошибка №4. Исправлять только код

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

Как избежать

Прежде чем приступить к рефакторингу, стоит ответить на важный вопрос — как так получилось, что нам приходится тратить столько времени на переписывание? Не возникнет ли проблема снова после того, как мы выкатим новый код? 

Важно не только исправлять плохой код, но и устранять причины, которые привели к его появлению. Например, перестроить внутренние процессы, как инженерные, так и продуктовые, а также поднять общий уровень hard skills разработчиков. Словом, убедиться, что если проблема и возникнет снова, то уже не в том масштабе.

Ошибка №5. Переписывать legacy и одновременно внедрять новый функционал

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

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

Как избежать

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

Ошибка №6. Проводить рефакторинг без участия PM’а или PO

Рефакторинг — технический процесс. Мы и так знаем, что и как делать, а Product Owner будет только мешать — долго разбираться в проблеме, делать кучу ненужной работы и требовать внимания. Размышляя таким образом, команда берется решать все самостоятельно. В процессе рефакторинга, столкнувшись с проблемами, они решают отказаться от поддержки небольшой части функционала, чтобы ускорить процесс, но остальное кропотливо переносят.

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

Как избежать

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

Ошибка №7. Пытаться создать идеальную архитектуру

Сейчас наш продукт написан плохо, но мы знаем, как создать правильную, качественную архитектуру, которая учтет все текущие требования и решит все проблемы.

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

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

Как избежать

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

Вывод

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

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

Комментарии (5)