Главная » Хабрахабр » «Синдром сантехника»: правила работы с легаси-кодом в тестировании

«Синдром сантехника»: правила работы с легаси-кодом в тестировании

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

В этом посте хочется рассказать, каких принципов придерживаются в Parallels (сразу спойлер – это принцип «не навреди»), и как мы поступаем, если решено все-таки «все переделать». Чем дольше «живет» проект, тем больше в нем накапливается «исторического», наследованного кода, и тем выше становятся шансы встретить горящие глаза поражённого «синдромом сантехника». Хотя в целом мы считаем, что синдром этот надо лечить, и что использование легаси иногда даже полезно, так как позволяет выпустить продукт вовремя и не тратить время на разработку своих технологий.

Например, Parallels Desktop разрабатывается уже более 15 лет. Когда работаешь с «программами-долгожителями», достаточно большой процент в них занимает легаси-код. Знакомая ситуация? С каждым годом команда расширяется, приходят новые люди, смотрят на то, что написано и заявляют: «Все криво, давайте оторвем руки программисту и все перепишем».

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

Мудрость, проверенная опытным путем

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

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

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

Что делать?

Шаг 1. Cмотрим, кто сказал
1. Фрилансер. Чаще всего полностью переделывать код кидаются люди, у которых нет опыта присоединения к большому проекту со стороны. Например, я сам сначала работал на фрилансе, писал проекты с нуля, и у меня, как у многих подобных разработчиков, сформировалась довольно устойчивая привычка – делать именно так, как мне удобно.

Малоопытный. 2. В итоге сложилось эдакое спагетти из взаимосвязанных между собой заплаток и костылей к этим багам. Иногда такие заявления свидетельствуют о недостатке квалификации самого человека в предметной области: он не знает истории проекта, и, например, того, что эта «страшная» (на его взгляд) конструкция получилась в результате того, что в процессе разработки люди наткнулись на баги внешних систем и начали их обходить. Такого знания всех существующих подводных камней у человека со стороны быть в принципе не может.

Д’Артаньян. 3. Человек бьет себя пяткой в грудь, и говорит, что сделает гениально, свежо, и всего за неделю, но может глубоко заблуждаться и относительно своих способностей, и потому, что совершенно упускает такие моменты, как тестирование и встраивание в существующую более крупную систему. Чаще всего это бывает у инженеров, не имеющих продуктового опыта и опыта работы в больших проектах, которые не понимают, какой ценой они достаются.

Высококлассный специалист. Единственный тип «заявителей», к которым стоит прислушаться, хотя и кидаться переделывать по его советам все равно не стоит, пока не осуществлен Шаг 2. 4. Но дело в том, что я ни одного человека уровня Senior с такими заявлениями не встречал. Не исключено, что нам достался профессионал ультра-класса, и он действительно сможет доказать, что у нас не так, и сможет сделать лучше. Когда человек дорастает до такого уровня, то уже может представить себе проект в целом и понимает все недостатки «революционного» метода.

Заставляем аргументировать
Первым делом человека нужно останавливать и проводить анализ его аргументов. Шаг 2. С оговоркой, что «синдромом сантехника» не начал страдать человек, сам пришедший тим-лидом. Инициировать это разбирательство должен тим-лид. Тогда разбор полета – дело проджект-менеджера, хотя, честно говоря, зрелый тим-лид никогда не инициирует полную переделку без серьезнейшей аргументации.

Он уже показал, что, несмотря на всю ужасность того, что там под капотом, он функционирует. Какие аргументы не пройдут:
«Мы напишем свое, с шахматами и поэтессами»
Чаще всего, если продукт уже давно существует на рынке, то он уже как-то работает. А поскольку такие вещи в принципе невозможно с наскока сделать, то, когда человек это говорит, то он либо не в теме, либо не в себе. Например, у нас есть Parallels Desktop (решение для запуска Windows и других операционных систем на Mac без перезагрузки), и иногда можно услышать от новичков: «как-то у вас тут все слишком сложно, давайте я напишу свою виртуальную машину». Нужно дать ему сначала набраться опыта в проекте и понять, почему именно так он был реализован изначально.

«Не технологично», «сделано на каком-то старье», «почему написано на Си, сейчас модно на Го писать». «Это некрасиво»
Беда в том, что часто других аргументов у человека и нет. Потому что когда выходишь за рамки своего одного кусочка кода, то начинаешь понимать, что твоя переделка может быть хуже, чем то, что было раньше. Это не аргументы для переделки системы. В Parallels такого я не видел, но в предыдущей компании нам пришлось полностью ощутить все последствия такого шага. Выглядеть может внутри красивее, а работать медленнее, что неприемлемо для продукта. Новое и красивое писали года полтора, но в итоге получилось так же ужасно и никаких преимуществ не дало. Решили, что некрасиво было реализовано семейство драйверов для определенного оборудования, и нужна более изящная и расширенная конструкция, которую будет легче мейнтейнить и добавлять в нее новые функции. А затраты ресурсов оказались очень большими: два разработчика сожрали у компании полтора года работы.

Почему многолетний код большого проекта лучше вообще не трогать

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

Да, существует такая методология разработки, когда сначала пишется документация, а потом строго по ней идет разработка, но она себя в 90-е еще показала как слишком инерционная для задач бизнеса. Можно сломать костыли
В любом проекте есть такая вещь, как kludge (более известная как «костыль»), и множество недокументированных вещей. И даже там приходится вносить какие-то изменения на ходу. Может быть, таким способом можно делать ракету, то есть в процессах, когда разработка идет несколько десятков лет, это оправдано, поскольку есть большие риски отклонений.

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

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

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

Стоит помнить, что такие люди находятся в группе риска, потому что могут уйти из компании на испытательном периоде (недаром говорят, что испытательный срок – не только для человека, но и для компании). Можно потерять инициатора и проект
«Синдром сантехника» поражает, в основном, новых сотрудников. Это очень опасная ситуация. Человеку дали карт-бланш, он начал переделывать, а потом заявил, что ему в компании кофе не нравится и ушел. Дальше кому-то (и отнюдь не энтузиасту) придется приводить это в работающий вид. Получится, что нового ничего нет, а старое уже сломали.

Что делать, когда решение не переделывать очевидно, а человек «горит идеей»?

Дать время остыть и подумать
Просто нужно дать время человеку, который пришел в большой существующий проект, на знакомство поближе. Ибо когда идея идет от человека, который давно работает в компании и конкретно с этим продуктом, то к его инициативам отнесутся гораздо серьезнее и будут разбирать его аргументацию. Нужно объяснить ему, что не стоит кидать в область, с которой ты еще недостаточно знаком и не знаешь текущей ситуации. Сомнительно, что только что пришедший человек, посмотрев на код, сумеет аргументированно объяснить, почему все неправильно и почему его надо поменять.

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

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

Когда переделывать все-таки надо

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

«Синдром сантехника» сработал: этапы переделки

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

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

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

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

Либо такой вариант: интерфейс фиксируется, делается реализация, а потом уже интерфейс начинает итерационно меняться.

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

Вместо заключения

Один мальчик родился с гайкой вместо пупка. И он периодически у родителей спрашивал, почему у него там гайка. Родители обещали рассказать ему об этом на 14-летие. Парню исполнилось 14. И вот он опять подошёл к отцу с матерью и спросил, почему у него гайка вместо пупка. Родители пообещали рассказать ему об этом, когда ему будет 18 лет. В 18 лет он спросил снова и тогда ему рассказали, что есть тропический остров на котором растет пальма, а под этой пальмой зарыт сундук. Там ответы на все его вопросы. Парень долго копил денег и всё таки отравился на этот остров. Нашёл пальму, откопал сундук, в котором лежал гаечный ключ. Не долго думая, он открутил гайку найденым ключом и у него задница отвалилась. Мораль: иногда просто не стоит искать приключения на пятую точку.


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

Перевезти дата-центр за 14 400 секунд

Всем знакома пословица «Один переезд равен двум пожарам». Смысл этой народной мудрости в том, что процесс переезда сопряжен со стрессами, суетой, переживаниями и, конечно, беготней, которые бывают и при пожаре, а подчас и с утратами ценного имущества. К тому же, ...

Дорожная карта математических дисциплин для машинного обучения, часть 1

Вместо предисловия Допустим, сидя вечерком в теплом кресле вам вдруг пришла в голову шальная мысль: «Хм, а почему бы мне вместо случайного подбора гиперпараметров модели не узнать, а почему оно всё работает?»Это скользкий путь — вы думаете, что достаточно пары ...