![](https://habrastorage.org/webt/gx/me/ai/gxmeai_2nkvbp7zbsov4hytkd0u.png)
Многие сталкивались с новичком, который приходил в проект и заявлял, что «все необходимо срочно переделать». А некоторые и сами это говорили или думали. Это — «синдром сантехника»: поведение, характеризующееся желанием все сделать по-своему, «правильно», при работе над новым проектом или при переходе на новую работу. А значит, существующий код, технологии или инструменты нужно переписать, желательно «под себя». Тема была бы банальной, если бы не повторялась так часто от проекта к проекту, с каждым новым набором штата.
Чем дольше «живет» проект, тем больше в нем накапливается «исторического», наследованного кода, и тем выше становятся шансы встретить горящие глаза поражённого «синдромом сантехника». В этом посте хочется рассказать, каких принципов придерживаются в Parallels (сразу спойлер – это принцип «не навреди»), и как мы поступаем, если решено все-таки «все переделать». Хотя в целом мы считаем, что синдром этот надо лечить, и что использование легаси иногда даже полезно, так как позволяет выпустить продукт вовремя и не тратить время на разработку своих технологий.
Когда работаешь с «программами-долгожителями», достаточно большой процент в них занимает легаси-код. Например, Parallels Desktop разрабатывается уже более 15 лет. С каждым годом команда расширяется, приходят новые люди, смотрят на то, что написано и заявляют: «Все криво, давайте оторвем руки программисту и все перепишем». Знакомая ситуация?
Прежде чем начать говорить, хорош или плох легаси-код, хотелось бы определиться с понятиями, кто и что под этим понимает. Обычно используют два определения: первое — это код, который не покрыт тестами. С точки зрения автоматического тестирования весь код не покрыт тестами. Второе, легаси-код – это код, который достался вам по наследству. Когда нужно понять, как он работает, но не у кого спросить. И приходится самостоятельно с ним возиться.
Мудрость, проверенная опытным путем
I. Лучшее — враг хорошего. Если унаследованный код или система выполняет всю необходимую функциональность с приемлемым качеством, то не надо его улучшать, лучше направить свою кипучую энергию на что-нибудь более полезное.
II. Из важного и нового выбирай важное, из равных выбирай новое. Если унаследованный код содержит важную функциональность и не покрыт тестами, необходимо уделить ему максимальное внимание, как в отношении переработки кода, так и в отношении покрытия его тестами. Если по важности легаси-код и новые фичи равны, то стоит сосредоточиться на новых фичах (разработка и тесты).
III. Если старое не поддаётся улучшению, строй новое рядом, потом выбрасывай старое. Если унаследованный код нужно, но невозможно изменить, используй старый код до тех пор, пока не напишешь и не отладишь новый. Когда новый код заработает, старый можно выбросить.
Что делать?
Шаг 1. Cмотрим, кто сказал
1. Фрилансер. Чаще всего полностью переделывать код кидаются люди, у которых нет опыта присоединения к большому проекту со стороны. Например, я сам сначала работал на фрилансе, писал проекты с нуля, и у меня, как у многих подобных разработчиков, сформировалась довольно устойчивая привычка – делать именно так, как мне удобно.
2. Малоопытный. Иногда такие заявления свидетельствуют о недостатке квалификации самого человека в предметной области: он не знает истории проекта, и, например, того, что эта «страшная» (на его взгляд) конструкция получилась в результате того, что в процессе разработки люди наткнулись на баги внешних систем и начали их обходить. В итоге сложилось эдакое спагетти из взаимосвязанных между собой заплаток и костылей к этим багам. Такого знания всех существующих подводных камней у человека со стороны быть в принципе не может.
3. Д’Артаньян. Чаще всего это бывает у инженеров, не имеющих продуктового опыта и опыта работы в больших проектах, которые не понимают, какой ценой они достаются. Человек бьет себя пяткой в грудь, и говорит, что сделает гениально, свежо, и всего за неделю, но может глубоко заблуждаться и относительно своих способностей, и потому, что совершенно упускает такие моменты, как тестирование и встраивание в существующую более крупную систему.
4. Высококлассный специалист. Единственный тип «заявителей», к которым стоит прислушаться, хотя и кидаться переделывать по его советам все равно не стоит, пока не осуществлен Шаг 2. Не исключено, что нам достался профессионал ультра-класса, и он действительно сможет доказать, что у нас не так, и сможет сделать лучше. Но дело в том, что я ни одного человека уровня Senior с такими заявлениями не встречал. Когда человек дорастает до такого уровня, то уже может представить себе проект в целом и понимает все недостатки «революционного» метода.
Шаг 2. Заставляем аргументировать
Первым делом человека нужно останавливать и проводить анализ его аргументов. Инициировать это разбирательство должен тим-лид. С оговоркой, что «синдромом сантехника» не начал страдать человек, сам пришедший тим-лидом. Тогда разбор полета – дело проджект-менеджера, хотя, честно говоря, зрелый тим-лид никогда не инициирует полную переделку без серьезнейшей аргументации.
Какие аргументы не пройдут:
«Мы напишем свое, с шахматами и поэтессами»
Чаще всего, если продукт уже давно существует на рынке, то он уже как-то работает. Он уже показал, что, несмотря на всю ужасность того, что там под капотом, он функционирует. Например, у нас есть Parallels Desktop (решение для запуска Windows и других операционных систем на Mac без перезагрузки), и иногда можно услышать от новичков: «как-то у вас тут все слишком сложно, давайте я напишу свою виртуальную машину». А поскольку такие вещи в принципе невозможно с наскока сделать, то, когда человек это говорит, то он либо не в теме, либо не в себе. Нужно дать ему сначала набраться опыта в проекте и понять, почему именно так он был реализован изначально.
«Это некрасиво»
Беда в том, что часто других аргументов у человека и нет. «Не технологично», «сделано на каком-то старье», «почему написано на Си, сейчас модно на Го писать». Это не аргументы для переделки системы. Потому что когда выходишь за рамки своего одного кусочка кода, то начинаешь понимать, что твоя переделка может быть хуже, чем то, что было раньше. Выглядеть может внутри красивее, а работать медленнее, что неприемлемо для продукта. В Parallels такого я не видел, но в предыдущей компании нам пришлось полностью ощутить все последствия такого шага. Решили, что некрасиво было реализовано семейство драйверов для определенного оборудования, и нужна более изящная и расширенная конструкция, которую будет легче мейнтейнить и добавлять в нее новые функции. Новое и красивое писали года полтора, но в итоге получилось так же ужасно и никаких преимуществ не дало. А затраты ресурсов оказались очень большими: два разработчика сожрали у компании полтора года работы.
Почему многолетний код большого проекта лучше вообще не трогать
Можно вообще убить свой проект
Где гарантия того, что вы вообще заново что-то напишете и оно будет корректно работать? Ведь этого сейчас еще нет. С точки зрения бизнеса жить нужно сегодняшним днем и обеспечивать непрерывность получения доходов.
Можно сломать костыли
В любом проекте есть такая вещь, как kludge (более известная как «костыль»), и множество недокументированных вещей. Да, существует такая методология разработки, когда сначала пишется документация, а потом строго по ней идет разработка, но она себя в 90-е еще показала как слишком инерционная для задач бизнеса. Может быть, таким способом можно делать ракету, то есть в процессах, когда разработка идет несколько десятков лет, это оправдано, поскольку есть большие риски отклонений. И даже там приходится вносить какие-то изменения на ходу.
А с точки зрения коммерческой разработки софта нет столько времени, чтобы сначала все-все-все учесть в документации, а потом по ней сделать. И получается, что у всех продуктов есть большой объем недосказанных данных. Встретились с какой-то проблемой внешней среды, например, какое-то железо работало в обход спецификации, сделали для нее воркэраунд. Во многих случаях, если это было относительно мелкое изменение, то оно достаточно часто забывается и не отражается в документации. Просто ее вклинят в код и чаще всего – с каким-либо мало вменяемым комментарием, к сожалению.
И начинается: давайте мы все эти костыли повыкидываем, так как это непонятно что и портит код. И не думают, к чему это приведет. Например, когда мы делали один из своих патчей для ядра Linux, то в одном месте грохнули такой костыль: очень уж он был некрасивый и при этом довольно плохо описанный. А потом в обсуждении узнали: определенное оборудование без этого кладжа не работает. Да, оно больше не выпускается, но все же есть у пользователей и работает. И потеря поддержки этого оборудования противоречит философии сообщества Linux. Пришлось переписать наш код так, чтобы этот воркэраунд сохранился один-в-один, и после этого все были удовлетворены.
Можно зря потратить ресурсы
Пример такой траты ресурсов приведены выше. Стоит понимать, что любая революция приводит к гражданской войне, к некоему периоду с ухудшением состояния дел, в который ничего работать не будет.
Можно потерять инициатора и проект
«Синдром сантехника» поражает, в основном, новых сотрудников. Стоит помнить, что такие люди находятся в группе риска, потому что могут уйти из компании на испытательном периоде (недаром говорят, что испытательный срок – не только для человека, но и для компании). Человеку дали карт-бланш, он начал переделывать, а потом заявил, что ему в компании кофе не нравится и ушел. Это очень опасная ситуация. Получится, что нового ничего нет, а старое уже сломали. Дальше кому-то (и отнюдь не энтузиасту) придется приводить это в работающий вид.
Что делать, когда решение не переделывать очевидно, а человек «горит идеей»?
Дать время остыть и подумать
Просто нужно дать время человеку, который пришел в большой существующий проект, на знакомство поближе. Ибо когда идея идет от человека, который давно работает в компании и конкретно с этим продуктом, то к его инициативам отнесутся гораздо серьезнее и будут разбирать его аргументацию. Нужно объяснить ему, что не стоит кидать в область, с которой ты еще недостаточно знаком и не знаешь текущей ситуации. Сомнительно, что только что пришедший человек, посмотрев на код, сумеет аргументированно объяснить, почему все неправильно и почему его надо поменять.
Если человека же такой отказ или предложение очень сильно демотивирует, то, это повод сделать пометку о том, что, возможно, данный разработчик не готов работать в команде и с ним могут дальше возникнуть сложности в общении (а это для нас очень важный фактор). Так как с ним потом тим-лиду придется работать отдельно, в «ручном режиме». Возможно, такому человеку стоит пересмотреть свои взгляды на карьеру и уйти в фриланс, где можно творить все, «как нужно».
Направить его энергию в другое русло
У большинства крупных продуктов всегда есть в наличии какие-то узкие места и проблемы, которые регулярно возникают, так как снаружи все меняется. Хотя нового человека, на мой взгляд, все-таки очень опасно пускать к коду, пока он пару месяцев не поработает с дебаггингом мелких багов, не познакомится с существующим кодом и не докажет уровень своей квалификации.
Можно дать ему задачу из каких-то боковых проектов, чтобы он запилил именно туда свое новое и посмотреть, что получится. Это при условии, что есть такие слоты в ресурсах, так как рисерч-задач тоже ограниченное количество, здесь как с венчурным бизнесом – в 100 компаний вложился, с одной получил отдачу.
Когда переделывать все-таки надо
Продукт в существующих условиях умирает
Аргумент за переделку – если внешняя среда изменилась настолько, что существующий продукт перестал работать. Например, когда выпустили новую операционную систему, на которую массово начали переходить пользователи, но в этой ОС что-то поменяли так, что ваш продукт, который под предыдущими версиями нормально работал, перестал функционировать или пользователю стало совершенно неудобно им пользоваться. Или когда платформа отмирает – в пример из старенького можно привести BeOS, под которым достаточно много работали с мультимедиа-продуктами, например, сочиняли музыку. Система умерла, а поскольку она была довольно самобытной, то коды из нее практически не переносили в другие системы. С самой OS BeOS то же самое случилось: были компьютеры Atom, на которые они ориентировались, а затем производитель перестал выпускать эти процессоры, и люди, которые писали под этот компьютер, фактически остались у разбитого корыта. И были вынуждены достаточно срочно адаптироваться под Intel, что у них получилось плохо — ниша была занята и там царила другая ОС. И чтобы хоть как-то продлить свою жизнь, им пришлось серьезно переделывать в сторону улучшения портируемости и так далее.
«Синдром сантехника» сработал: этапы переделки
Нужно делать эволюционно и параллельно, не ломая систему. Процесс и этапы переделки зависят от того, меняем ли весь продукт целиком или какую-то существенную его часть. Если весь продукт, то это фактически начало с нуля нового проекта. Но в большинстве случаев все-таки меняют часть, так как в первом случае пройдет не один год, прежде чем новая кодовая база наберет стабильность и соответствие потребительским качествам, чтобы удовлетворять хотя бы тому уровню, который был.
Если заменять компонент, то желательно делать так: если внешний интерфейс не требует изменения, то мы спокойно делаем вторую реализацию. Желательно сразу найти линии раздела: здесь остаётся старое, а вот тут уже можно переделывать, найти точки входа. И так, сохраняя интерфейс, поменять начинку.
Это как с машиной, у которой бензиновый двигатель решили заменить электродвигателем. Для пользователя мало что поменялось: остался тот же корпус, четыре колеса и руль. А под капотом может быть все другое.
Если удается найти такую точку раздела, то тогда можно эволюционно переделывать и тот, кто стоит по ту точку раздела, может даже не заметить изменений (кроме, будем надеяться, улучшения качества работы). А потом в процессе внутреннего тестирования переключиться и сохранить продукт. К сожалению, далеко не всегда это возможно, и тогда переделка может привести к катастрофе.
Либо такой вариант: интерфейс фиксируется, делается реализация, а потом уже интерфейс начинает итерационно меняться.
Серьезную переделку есть смысл начинать на боковых ветвях и пока она не получит законченный вид, в основной продукт не интегрируется. Даже применительно к подсистемам, хуже, если под этим именем мы начали делать совсем что-то новое, и команда распалась, то нет продукта вообще.
Вместо заключения
Один мальчик родился с гайкой вместо пупка. И он периодически у родителей спрашивал, почему у него там гайка. Родители обещали рассказать ему об этом на 14-летие. Парню исполнилось 14. И вот он опять подошёл к отцу с матерью и спросил, почему у него гайка вместо пупка. Родители пообещали рассказать ему об этом, когда ему будет 18 лет. В 18 лет он спросил снова и тогда ему рассказали, что есть тропический остров на котором растет пальма, а под этой пальмой зарыт сундук. Там ответы на все его вопросы. Парень долго копил денег и всё таки отравился на этот остров. Нашёл пальму, откопал сундук, в котором лежал гаечный ключ. Не долго думая, он открутил гайку найденым ключом и у него задница отвалилась. Мораль: иногда просто не стоит искать приключения на пятую точку.