Технический долг — особый вид долга: мы занимаем у самих себя, причем нередко с большими процентами. Несмотря на то, что платить по счетам рано или поздно приходится, устранение техдолга редко относится к насущным бизнес-задачам. Бизнес либо откладывает это «на потом», либо вообще не рассматривает как проблему. Я думаю, главная причина непонимания — в том как мы, инженеры и разработчики, пытаемся объяснять бизнесу, почему важно избавляться от техдолга. Мы транслируем наше видение из нашего технического мира, забывая, что у бизнеса другие критерии оценки важности проблем. Мой доклад, с которым я выступил на DevOpsConf 2021, как раз о том, как устранить это непонимание и «продать» бизнесу технический долг. Представляем видео с докладом (~50 минут) и основную выжимку из него в текстовом виде. Бывает, вы придумываете какое-то классное, проработанное до мелочей решение, показываете его коллегам и руководству. Все говорят: молодец, отлично, только давай теперь сделаем что-нибудь попроще и побыстрее — у нас в приоритете бизнес-задачи, и мы просто не можем тратить на это столько времени. Что получается: 1. Инженеры грустят. Им не дают делать хорошее решение, они вынуждены делать очередные костыли. 2. Технический долг растет. Инженеры понимают, что с ним потом всё равно что-то нужно будет делать. Но при этом: 3. Компания остается конкурентоспособной. Потому что если бы компания выбирала только технически-правильные решения, она бы проигрывала тем, кто делает хуже, но быстрее. Конечно, с точки зрения инженера эта ситуация похожа на бесконечный День сурка: каждый день его заставляют делать плохие решения. Кажется, что это ситуация, из которой нет какого-то адекватного выхода.  Однако я считаю, что выход есть. Можно достичь того самого баланса, когда техдолг не растет с космической скоростью, инженеры не грустят, но приоритет остается на бизнес-задачах. За 10 лет работы системным администратором, DevOps-инженером и менеджером в разных компаниях мне удалось посмотреть на проблему технического долга с разных сторон. И кажется, я нашел тот самый «потерянный элемент», который можно использовать для комфортной работы с техническим долгом. Кто-то спросит: а какая связь между системным администратором и техническим долгом? Вроде бы это проблема из мира разработки, и связана она непосредственно с разработкой кода. Отвечу так. Если посмотреть на современный мир ИТ, то у нас уже всё — код. Я уверен, что в ближайшее время не будет разработчиков, тестировщиков, инженеров эксплуатации. Мы все превратимся в инженеров-разработчиков. Когда-то давно, на заре карьеры у меня была довольно простая задача: ускорить процесс создания test- и production-окружений. Чтобы это реализовать, нужен инфраструктурный код и соответствующий инструмент. В то время мой выбор пал на Ansible. При этом было важно определиться с количеством Ansible-ролей; первоначально я решил, что их у меня будет 50. Но определение количества ролей всё еще не дает ответа на вопрос, сколько всего нужно времени на разработку. Для этого нужно понять:  из каких этапов состоит процесс разработки, и сколько времени занимает каждый из них. Если делать всё по-правильному — с разработкой CI/CD и тестов, — итоговое расчетное время может озадачить. 700 дней — это почти 2 года. За это время в компании может измениться всё, что угодно. Например, бизнес может решить, что пора заезжать в Kubernetes. А когда мы переделаем роли под Kubernetes, окажется, что и роли уже не нужны, потому что появился, например, Deckhouse. И всё это время компания будет платить нам зарплату за работу, которая никому не нужна. Вариантов несколько.  1. Взять больше DevOps-инженеров. Вариант неплохой, но есть некоторые нюансы. Куда девать инженеров после того, как они сделают всю эту работу?  Возможно, мы изначально выбрали не тот инструмент IaC (надо было не Ansible, а, например, Bash), и переходить на другой будет очень сложно.  2. Сократить количество ролей. То есть не делать всё сразу, а выбрать, допустим, 10 самых востребованных ролей. Так мы уменьшим общее время на разработку до 140 дней. Но этого всё равно долго. 3. Отказаться от CI/CD и от тестов. Можно всё делать на своем ноутбуке и тестировать в процессе разработки вручную. В сочетании с сокращением количества ролей мы уменьшим общее время до 30 дней. Вроде бы отличный результат. Уже через 30 дней инженер увидит результат своей работы, а компания начнет получать business value. Однако фактически, отказавшись от важных этапов разработки, мы начинаем плодить технический долг. Пример с сокращением цикла разработки до 30 дней — скорее антипример, так делать, конечно, не стоит. Но кое-что все-таки можно сократить — например, количество ролей с 50 до 10. Потому что нам важно как можно быстрее получить обратную связь, посмотреть как это работает и учитывать в дальнейшем. То, что мы делаем только базовую функциональность для ролей, которую дальше будем развивать, вполне укладывается в концепцию continuous improvement. А что делать с тестами и CI/CD? Это и будет наш технический долг. Возможно, кто-то считает, что это никакой не технический долг, а просто типичная попытка выкатить всё побыстрее в продакшн. Но давайте посмотрим на определение техдолга на Википедии: «Метафора программной инженерии, обозначающая накопленные в программном коде или архитектуре проблемы, связанные с пренебрежением к качеству при разработке программного обеспечения и вызывающие дополнительные затраты труда в будущем».  Получается, мы берем в долг у самих себя, но в будущем. И то, что я предлагаю сделать — это действительно технический долг. Вместе с тем это осознанный выбор, который сильно отличается от просто плохо сделанной работы. В моем понимании технический долг — это когда мы ускоряем наши процессы, чтобы достичь какого-то результата, откладывая что-то на потом. Притом мы понимаем, что в дальнейшем это «что-то» может привести к проблемам. Когда мы берем кредит в банке, у нас есть понятный график платежей по кредиту, нам проще возвращать долг.  Но в случае с техническим долгом мы договариваемся сами с собой. Это так же, как обещать себе: завтра я начну заниматься спортом, завтра я начну учить английский, с понедельника я начну вставать в 7 утра, чтобы всё успевать. Откладывать выплату таких «долгов» проще, мы всегда найдем причину для этого.  В отличие от договоров с самим собой, на работе нам приходится договариваться с коллегами, с руководством. В какой-то момент приходит понимание, а за ним и желание наконец собраться и начать отдавать технический долг. Вы формируете пул задач, пытаетесь положить его в поток с бизнес-задачами. И тут появляются менеджеры, которые говорят: а давай мы сделаем это завтра. Почему менеджеры, которые управляют бизнес-задачами, которые умеют их приоритизировать, не понимают, что нужно работать в том числе и с техническим долгом? Чтобы ответить на этот вопрос, достаточно посмотреть на процесс разработки глазами неинженера. В проекте есть видимые и невидимые изменения. Первые видимые изменения — новая функциональность. Это и есть те самые бизнес-задачи, на которые выделяют все время, потому что бизнес зарабатывает за счет новых фич. Иногда для внедрения новой функциональности требуются архитектурные изменения — например, нужно добавить 5 виртуальных машин или установить новую БД. Хотя архитектурные изменения относятся к типу невидимых, время на это выделяется так же легко. Их связь с новой функциональностью линейная: пока мы не изменим архитектуру, новые фичи не появятся. После того, как мы разрабатываем новую фичу, появляется еще одна видимая проблема — баги. Все понимают, что пока мы не пофиксим баги, новая фича не заработает и не начнет приносить прибыль. Получается, главное для бизнеса — выпустить новые фичи и пофиксить баги. А вот когда инженеры приходят с техдолгом, бизнес не понимает, зачем этим заниматься: баги исправлены, всё работает. Проблема в том, что баги влияют на наш проект здесь и сейчас, а техдолг влияет на него в будущем. И это очень важный момент: технический долг относится к невидимым изменениям и в глазах бизнеса не играет решающей роли. Можно было бы предложить решить проблему на корню — делать хорошее решение изначально. Да, разница между 30 и 140 днями выглядит достаточно большой. Но это все равно лучше, чем 700 дней. И на первый взгляд такой подход выглядит как универсальное решение, с помощью которого мы можем избавиться от техдолга. Но, как всегда, есть нюансы. Мы во «Фланте» занимаемся Kubernetes и знаем про него очень много вещей, в том числе не всегда очевидных. В частности, мы знаем, что новые релизы K8s выходят в среднем раз в 90 дней. Если мы делаем какую-то фичу 140 дней, к тому моменту, когда мы ее сделали, у нас уже в проекте появился технический долг — независимо от того, хороша или плоха фича.  Это относится не только к Kubernetes. Ведь для разработки мы используем операционные системы, системы контейнеризации, языки программирования, библиотеки, фреймворки и так далее. Всё это разрабатывают другие компании. И как бы мы хорошо не старались, технический долг у нас в любом случае появляется. Одно из косвенных подтверждений этого тезиса — явление, известное как dependency hell, по-русски — «ад зависимостей». Я лично столкнулся с ним, когда работал над одним микросервисом. Проекту было на тот момент около полутора лет. В нем нужно было очень срочно заменить одну зависимость. Выглядело как очень простая задача: меняешь пару цифр в коде, коммитишь это в Git — и всё. Но в итоге пришлось поменять 50% всех зависимостей и 30% кода. Работа заняла 14 дней.  В тот момент решением для нас стала утилита dependabot, которая ходит по разным репозиториям, анализирует зависимости и посылает пулл-реквесты, когда в зависимостях появляются какие-то обновления. По сути, мы взяли большой кусок технического долга и поделили его на маленькие кусочки. Инженер тратил 10-15 минут в неделю на то, чтобы поддерживать проект в актуальном состоянии.  Такие маленькие задачи очень легко подкладывать в поток бизнес-задач. Но здесь есть две потенциальные проблемы: если инженер увлечется, он может начать делать много маленьких задач техдолга в ущерб бизнес-задачам; далеко не все задачи можно разделить на мелкие подзадачи и еще меньше тех, которые можно автоматизировать. Есть отличный способ, как с этим бороться — это еще один пример из моей практики. Я участвовал в проекте, у которого было очень ограниченное время запуска: 4 месяца от состояния «у нас ничего нет» до «мы в production». В процессе было сделано много упрощений и допущений, одно из которых — то, что вложения (?) будут храниться в базе данных. Почему? — потому что транзакционность, потому что так проще, потому что мы знаем, как это сделать. Но потом, когда-нибудь, мы, конечно, вынесем это из БД. В результате через полгода БД весила уже 8 ТБ. Помимо этого, у базы было три реплики в разных дата-центрах. А еще были резервные копии на 15 ТБ. Инженерам было достаточно тяжело всё это обслуживать:  на то, чтобы поднимать production-like-окружение, нужно много времени;  на то, чтобы восстановить репликацию, если она сломалась, — тоже;  нужен был DR-план на тот случай, если на все дата-центры упали метеориты. Со всеми этими мыслями, а также предложениями по оптимизации архитектуры, я пришел к руководителю проекта. Понятно, что разговор ни к чему не привел. Через некоторое время я предпринял вторую попытку, но в этот раз использовал уже другие аргументы. Главная идея была в том, чтобы уменьшить дублирование данных и сократить стоимость чека за аренду инфраструктуры в облаке. После внедрения решения экономия составила бы 35 тыс. руб. в месяц при сроке окупаемости в 3 месяца. То есть через 3 месяца решение станет прибыльным. На этот раз ответ руководителя был положительным. Почему так получилось?  Всё просто. Когда мы приходим к руководству, ему далеко не всегда понятны технические подробности. Язык бизнеса — это язык цифр и денег. И если мы приходим с понятными для бизнеса данными, мы получаем понятный ответ. Такой подход решает еще одну проблему. Большинство инженеров в душе — перфекционисты, они стараются делать идеальные решения. Но когда мы смотрим на решение не только с точки зрения технической идеальности, а еще добавляем туда стоимость этого решения, мы получаем правильную формулу.   Другие плюсы подхода: мы знаем, когда нужно остановиться и перестать улучшать свое решение; мы можем превратить задачи с техническим долгом в бизнес-задачи, и менеджеры могут правильно их приоритизировать. Остается еще один важный вопрос. В большинстве случаев у нас есть какой-то технический долг, о котором мы до поры до времени не знаем. Я нашел хороший инструмент, чтобы его выявить — с помощью практики управления инцидентами, известной как post mortem. Проще говоря, это анализ отчета об инциденте. В отличие от большинства отчетов, которые мы просто кладем в сейф и забываем о них, отчет об инциденте — очень полезный документ. Его составляют все, кто так или иначе причастен к инциденту.  Post mortem — это: Способ посмотреть на картину целиком и найти техдолг. Зафиксировать техдолг и рассчитать ущерб от него. Получить статистику и аргументы для продажи техдолга. Чтобы понять из отчета post mortem, какие проблемы относятся к багам, которые нужно исправлять, а какие пока лучше отложить в техдолг, поможет простой алгоритм: Проблема низкого приоритета технических задач вроде ликвидации техдолга — не в том, что у бизнеса приоритет на бизнес-задачи; а решение — не в том, чтобы повысить приоритет технических задач. На мой взгляд, оптимальное решение — это конвертация технических задач в бизнес-задачи. Это помогает менеджерам правильно их оценивать, а инженерам — понимать, насколько идеально решение не только с технической, но и с финансовой точки зрения. Видео с выступления (~46 минут): Презентация доклада: Читайте также в нашем блоге: доклад «Как правильно сделать Kubernetes» (Дмитрий Столяров; май'2021 на DevOpsConf); доклад «Управление распределенной командой в режиме многопроектности» (Сергей Гончарук; сентябрь'2019 на Saint TeamLead Conf); доклад «Performance Review и выявление тайного знания» (Игорь Цупко; апрель'2019 на KnowledgeConf). Ведущий инженер