Continious Refactor +5


Объясняем бизнесу, зачем нужен рефакторинг

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

После этого возможны сценарии:

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

  • менеджер не понимает, просит объяснить, что за зверь этот рефакторинг; какую ценность он несет для бизнеса; как после него маркетингу прикрутить табличку 2.0; что отвечать клиентам, которые будут кричать что не видели обновлений уже примерно 9000 лет и пора валить.

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

Привет, Хабр! Меня зовут Александр, я работаю руководителем разработки в блоке ИТ-развития корпоративного бизнеса в РСХБ-Интех. Моя роль - технический лид разработки, мой путь я прошел от рядового программиста, до чистого управленца. Но на текущем месте я вернулся ближе к разработке, так как только её я умею делать хорошо. Я пришел сюда не так давно, поэтому пока не могу рассказать о нас настолько ярко, как о моих прошлых опытах. Эта статья - практически чистый поток сознания о самой, пожалуй, большой моей боли. 

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

Вот смотрите: есть у вас машина, прекрасная, быстрая, удобная, кушает какое-то сносное количество топлива, в обслуживании требует немного денег, во всем вас устраивает, но потихоньку стареет. Постепенно на рынке начинает распространяться нововведение - например, принципиально иное топливо - неуглеводородный бензин из кореньев (сокращенно “нубик”).

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

Вы интересуетесь у других автовладельцев, что случилось и получаете длинную хвалебную тираду, после которой уже всерьёз думаете попробовать его. Но есть проблема - горловина вашего бензобака не совместима с новым шлангом. Ок - думаете вы - не очень то и хотелось. Проходит еще N+1 месяцев, и вот приехав на заправку, вы не находите 95-й. И на ближайших тоже, и в соседнем районе тоже, и вообще после поисков в интернете вы узнаете, что таких заправок осталось всего 2 на весь город, из-за чего возникает много досадных трудностей. Но ведь ваша машина вас устраивает, зачем тратить время и деньги на замену, привыкать к новой - вы всё еще не видите необходимости менять её. Вы вообще считаете, что мода на нубик это что-то временное, и скоро всё станет как раньше.

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

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

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

Наконец вы получаете долгожданный звонок и летите в гараж, где не сразу узнаете вашу машину. Среди прочего, выхлопная труба теперь выведена в салон, но это не беда - можно ездить с открытой форточкой. Но зато машина заводится уже не 40 секунд, а 27. Стала ездить на 1,48 % быстрее и может вместить не 4 человека, а 4,52. Отлично - думаете вы и почти счастливый уезжаете. На выезде из гаражей ваш взгляд останавливается на билборде - “система обеспечения полета на ядерном топливе”.

ЧЯДНТ?

Итак, объясним аналогию. Жизнь нашего героя - ИТ проект. Машина - его важный модуль. Появляется новая технология в автомобилестроении, которая постепенно становится стандартом индустрии. Специалисты, хорошо знакомые со старой - либо переквалифицировались, либо кратно увеличили ценники, компенсируя сужение рынка труда. Часто при этом скилл они не наращивают, потому что это и не требуется - всегда найдется нишевый пользователь их “уникальных” умений.

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

Очевидным выходом из ситуации было бы потратить время и деньги в момент массового тиражирования новой технологии, поменять машину на такую же классом, или, проанализировав кейсы использования, оптимизировать ожидания, и дальше уже не думать об устаревании несколько спокойных лет. Да, одномоментные траты были бы выше, но в целом после нескольких релизов они бы сполна окупились за счет привнесения дополнительной ценности продукта для бизнеса. И вот почему-то на примере с автопромом все это понимают, а на ИТ-проектах уже через 20 секунд объяснений кажется, что у партнеров по обсуждению какой-то блуждающий взгляд… Для того чтобы объяснить людям, далеким от осмысленного запуска IDE, зачем в среднесрочной перспективе нужно всегда переводить проект на использование более современных решений, стоит для начала дать им простую установку - при создании любой технологии, она опирается прежде всего на современные технические, архитектурные, управленческие подходы, но никак не модную конъюнктуру. 

Простой пример, выходит bleeding edge технология: какие-нибудь новейшие процессоры с убер-пупер-технологичными конвейерами для ускорения заказа пиццы. Маркетинг сходит с ума от счастья, рождая все новые и новые причины купить этот замечательный “продукт”. Но технари - не маркетинг, им надо практику - начинается тиражирование технологии, поиск новых путей ее применения. У нее появляется два пути развития: остаться поделием сумрачных гениев и замкнуться внутри ограниченного сообщества — или получить путевку в массы путем раскрытия производителем спецификаций и выпуском драйверов.

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

Через время аналогичные решения уже есть у каждого производителя и настает замечательный момент унификации. Обычно в этот момент рождается большой красивый framework или, на худой конец, набор API для ОС. Всё - теперь это стало индустриальным стандартом. Теперь любой новый проект без использования “этих ваших конвейеров” обречен на прозябание на обочине истории, потому что никто из специалистов не захочет тратить на него усилия. Или ему повезет найти евангелиста, который вытащит его из забвения путём, внезапно, внедрения поддержки убер-пупер-технологичных конвейеров.

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

В общем всё старое таким и остается, а с каждым новым витком технологий оно устаревает все сильнее и сильнее. Конечно, те же самые framework будут до последнего держать обратную совместимость, но момент появления надписи “будет исключено в следующем релизе” неминуем. Технологическое развитие связанных проектов на этом останавливается навсегда, потому что объем не закрытого технического долга уже больше стоимости команды. 

Пациент скорее

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

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

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

Мечта… И как ее достичь, когда вокруг бегают менеджеры и кричат о важности выпуска нового ”билда” (предупреждение: применяйте сленг только там, где никто его не подхватит, а то потом стыда не оберетесь)? Потому что дать вам возможность так красиво поиграться с проектом, как я описал выше - это оплатить несколько месяцев работы всей команды - разработчиков, аналитиков, тестировщиков - при околонулевом внешнем профите. А вот тут очень хорошо применить практику непрерывного рефакторинга. Вообще, в своей работе, я сталкивался с двумя полярными концептами по отношению к переработке кода: пока продукт окончательно устареет мы уже будем писать другой/в другой компании/обоснуем необходимость замены его целиком на новый; мы построили классную архитектуру, написали классный код, давайте не дадим ему устареть;

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

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

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

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

Тут мы получаем помимо основного плюса, в виде актуализации кодовой базы и догонки технологии, еще и кучу косвенных - скилл всей команды растет вместе с внедрением фичи; закрываем большой кусок технического долга; решаем десяток-другой лежалых или похороненных багов. В итоге, новое решение тестируем, выводим на продуктив, а потом начинаем рекламировать - идем к архитекторам, аналитикам и говорим “смотрите, как я классно умею, а теперь придумайте, как это все углубить и использовать вообще везде”. А если решение еще и увеличивает ценность для бизнеса, то тут вообще нужно собирать целое совещание! Или просто рисоваться перед коллегами, что мы оптимизировали выполнение кода генерации эдемских кущ на 6,28%

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

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




К сожалению, не доступен сервер mySQL