AI написал проект, команда ушла, а поддерживать теперь вам

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

Ситуация. Вам передали сервис на Rust + MongoDB. Большую часть кода написали AI-агенты, а разработчики, которые начинали проект, переключились на другие задачи или ушли из компании. Автотестов почти нет либо они не покрывают критические сценарии, документация ограничивается README с инструкцией по запуску и кратким описанием проекта. При этом сервис уже используют клиенты, бизнес ждёт новые функции, а от вашей команды ожидают прежней скорости разработки: предыдущая команда ведь смогла быстро запустить продукт, и тот уже приносит деньги.

Никто в новой команде раньше всерьёз не работал ни с Rust, ни с MongoDB. Разработчики знакомы с основными концепциями, но не представляют, как именно этот сервис поведёт себя при росте нагрузки или отказе одного из компонентов. Подобные проекты существовали и до AI: люди оставляли после себя системы без тестов, а документация нередко жила только в их головах(сам столкнулся с таким). Разница в скорости, теперь большой объём кода появляется быстрее, чем команда накапливает опыт работы с ним, а быстрый запуск создаёт ожидание, что дальше разработка пойдёт так же быстро. В итоге у вас есть работающий продукт, непонятная архитектура, незнакомый стек и команда, которой нужно всё это поддерживать.

Не начинайте с переписывания(очевидный совет №1)

Первое желание при знакомстве с таким проектом обычно сказать, что всё сделано неправильно, и предложить переписать его на знакомом стеке. Особенно если команда хорошо знает один стек, а получила Rust и MongoDB без сохранившегося обоснования выбора технологий. Зачем разбираться в чужих решениях, если можно использовать привычные инструменты?

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

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

Первые две недели

Команда не сможет на месяц отказаться от продуктовых задач и спокойно изучать Rust. Да и месяца для этого не хватит. Нужен не абстрактный план «быстрее во всём разобраться», а последовательность действий с проверяемым результатом.

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

Сразу после запуска нужно разобраться с CI/CD, а также понять как выполняются миграции БД, кто может откатить релиз и что произойдёт после неудачного развёртывания? Заодно нужно выяснить, куда приходят алерты, как собираются логи и метрики, кто начнёт диагностику при сбое и что делать при отказе критической зависимости.

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

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

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

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

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

Первые дни    → доступы, запуск, эксплуатация и восстановление
Первая неделя → карта системы, критические пути и зависимости
Вторая неделя → проверка рисков и безопасных границ изменений

Этот план задаёт порядок исследования, а не обещает, что любой проект получится полностью изучить за две недели.

Не все неизвестные одинаково опасны

Допустим, в проекте 1000к строк кода, почти нет нормальных тестов и используется незнакомая БД. Что делать дальше: изучать MongoDB, писать тесты для каждого метода или заказывать архитектурное ревью? Я бы начал с последствий возможного отказа, тем более что внешне «аккуратный AI-проект» может создавать ложное ощущение надёжности. Люди и раньше оставляли после себя дублирование, устаревшие комментарии и сомнительные архитектурные решения, но теперь агент способен за короткое время создать столько кода, проблем абстракций и интеграций, сколько команда не успеет проверить.

Представим сценарий оформления покупки: сервис создаёт заказ в MongoDB, а затем отправляет событие в Kafka(про outbox, конечно же забыли). Пока всё работает, проблемы не видно. Но если Kafka окажется недоступна, заказ останется в базе, а другие сервисы могут о нём не узнать. Из кода при этом неясно, предусмотрена ли повторная отправка и что произойдёт при получении одного сообщения дважды. Это уже не абстрактный теx. долг, а риск потерянной или повторно выполненной операции. Нужно выяснить, заметит ли команда неконсистентность данных раньше, чем в поддержку придёт срочный тикет с темой «Деньги списали, а заказа нет!».

Сервис заказов → MongoDB: заказ сохранён
       │
       └──────→ Kafka: ошибка публикации
                          ↓
                Другие сервисы не получили событие

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

Отдельно стоит проверить права доступа и зависимости. Агент мог корректно реализовать основной сценарий, но забыть проверку полномочий в отдельной ручке API, оставить в репозитории некоторые секреты или позволить пользователям напрямую обращаться к диску(и такое видел, когда экшен выполнял eval). Рядом может находиться модуль отчётов на который не хочется смотреть, его неприятно поддерживать, но цена возможной ошибки совсем другая. Поэтому сначала стоит исследовать операции с деньгами, пользовательскими данными, доступами и необратимыми изменениями, затем смотрим в сторону интеграций, фоновых задач и участки, от которых зависит доступность продукта. Для каждого существенного риска полезно зафиксировать четыре вещи:

  1. Что может произойти?

  2. Почему мы считаем это возможным?

  3. Как проверить предположение?

  4. Кто отвечает за проверку?

Аккуратно организованный код ещё не означает проверенную систему. Нужно отделить гарантии, подтверждённые тестами и наблюдениями, от утверждений, которые существуют только в объяснениях AI. Именно такие неподтверждённые гарантии стоит проверять в первую очередь.

Не пишите тесты только ради покрытия(очевидный совет №2)

После первичного исследования появляется соблазн попросить AI написать тесты на весь проект. Агент пройдёт по функциям, подготовит моки, сгенерирует данные, добьётся зелёного CI — и вот уже отчёт показывает 90% покрытия. Однако агент может закрепить тестами ошибочное поведение. Допустим, обработчик неправильно рассчитывает скидку: AI изучит текущую реализацию и создаст проверки именно для этой формулы. Тесты пройдут, покрытие вырастет, но баг останется. Поэтому сначала нужен независимый источник ожидаемого поведения: требования, примеры реальных операций, согласованные бизнес-правила или контракты с внешними системами. Если ничего такого нет, правила придётся восстанавливать вместе с аналитиками, владельцем продукта и другими участниками команды. Здесь лучше задать лишний вопрос, чем уверенно закрепить тестом ошибку, за последствия которой команда будет отвечать во время инцидента.

Я бы не ставил целью условные 80% покрытия. Вместо этого выбрал бы несколько критических сценариев и проверил их целиком: создание заказа, повторный запрос с тем же идентификатором, ошибку сохранения, недоступность внешнего сервиса/компонентов и повторную доставку события. Особенно полезны интеграционные тесты с реальной БД в тестовом окружении, а не мок репозитория, который воспроизводит наши же предположения. В зависимости от сценария понадобятся и проверки на уровне API или взаимодействия нескольких сервисов.

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

Как изучать технологию, которую никто не знает

Допустим, команда всегда работала с PostgreSQL, а новый проект использует MongoDB. Никто не понимает особенностей модели данных, гарантий согласованности и ограничений транзакций. Можно отправить всех на курсы, попросить AI объяснить устройство Mongo или нанять человека с подходящим опытом. Но пытаться за пару месяцев сделать всех разработчиков экспертами в новой технологии бессмысленно.

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

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

Не собирайте всё понимание у одного человека

Представим, что вы подняли проект, восстановили архитектуру, написали первые тесты и разобрались с Mongo(добавили ее также в скиллы на linkein). Ситуация постепенно улучшается, но теперь вся информация сосредоточена у вас. Команда продолжает выполнять задачи, а с каждым нестандартным вопросом приходит к вам: почему здесь всё работает именно так, что делать при недоступности Kafka и как безопасно изменить схему документа?

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

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

Я бы строил погружение вокруг конкретных сценариев. Сначала разработчик самостоятельно поднимает сервис и выполняет одну бизнес-операцию. Затем прослеживает её путь от входящего запроса до изменения данных. Следующим шагом становится небольшое изменение, которое нужно провести через тесты, ревью и тестовое окружение.

После этого можно дать задачу другого типа — воспроизвести сбой. Например, сделать внешнюю зависимость недоступной в локальном или тестовом окружении. Я сам останавливал postgre в docker compose, чтобы посмотреть, как поведёт себя приложение и восстановится ли соединение после запуска базы. Затем разработчик выясняет, где появилась ошибка, успели ли измениться данные и по каким логам или метрикам это можно увидеть.

Такое упражнение гораздо лучше показывает глубину понимания. Полезно также попросить человека объяснить изученный участок другим: разобрать сценарий, показать ограничения и рассказать, где искать причину проблемы. Если разработчик способен самостоятельно пройти путь от симптома до причины, это уже признак реального погружения. Такой процесс нужен не только новичкам: для команды, впервые получившей проект, он работает точно так же.

Как распределить исследование между разработчиками

Допустим, в команде пять backend-разработчиков. Никто хорошо не знает Rust и MongoDB, но продуктовый бэклог никуда не исчез. Можно назначить одного ответственным за проективароние БД, второго за взаимодействия с Kafka(пусть смотрит как прикрутить outbox, и другие штуки), а остальных оставить на функциях. Тогда каждый критический компонент будет понимать ровно один человек, и при его отпуске/увольнении часть работы остановится.

Я бы распределял исследование не только по технологиям, но и по сквозным сценариям. Один разработчик изучает создание заказа и запись данных, второй — обработку событий и повторные попытки, третий — сборку и деплой, четвёртый — диагностику и метрики, пятый — тестирование критических сценариев. Это не постоянные зоны ответственности и не работа в одиночку.

У каждого исследования должен быть второй участник, который не просто читает готовую документацию, а проверяет выводы, задаёт вопросы и может воспроизвести результат. Если первый объясняет поведение транзакции в MongoDB, второй должен также понимать нюансы. Если команда разобралась с обработчиком событий, следующее изменение в нём полезно поручить другому человеку. Совместная работа и смена ролей позволяют распространять знания без отдельного учебного проекта.

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

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

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

Создание заказа   → Вова + Денис
Обработка событий → Денис + Рома
Сборка и деплой   → Рома + Ваня
Диагностика       → Ваня + Вова
                         ↺ ротация

У каждого критического сценария есть два участника, а ротация не даёт знаниям закрепиться за одним человеком.

Не нужна документация ради документации(очевидный совет №3)

При наследовании неизвестного проекта хочется быстро получить документацию. Можно попросить AI описать каждый модуль, нарисовать диаграммы последовательностей и подготовить md файлики для всех компонентов. Получится огромный набор документов, который создаёт ощущение порядка и мысль: «Когда будет время, прочитаю».

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

Не надо превращать документирование в отдельную бесконечную работу. Полезнее обновлять инструкции по мере решения реальных задач. Нашли проблему с восстановлением БД — описали и проверили процедуру. Разобрались с повторной доставкой события — зафиксировали гарантии и ограничения. Обнаружили неочевидное бизнес-правило — согласовали его с продактом и добавили тест. Так документация будет расти вместе с пониманием системы.

AI помогает исследовать, но не подтверждает выводы

Если AI умеет анализировать логи, читать код и предлагать исправления, зачем разработчикам самостоятельно разбираться с инцидентами? Я не предлагаю отказываться от AI. При работе с незнакомым проектом агент может быстро найти все места записи в коллекцию, восстановить цепочку вызовов, предложить сценарии отказа или помочь подготовить интеграционные тесты. Это экономит время на механическом поиске.

Однако между «AI помог восстановить цепочку обработки запроса» и «AI утверждает, что здесь всё нормально» есть принципиальная разница. Второй ответ сам по себе ничего не доказывает. Я бы использовал агента для поиска гипотез, а не как единственный источник подтверждения корректности системы. Инженер должен уметь объяснить, на каких данных основан вывод, каким экспериментом его проверить и что будет означать отрицательный результат. В рамках погружения иногда полезно дать человеку сначала самостоятельно локализовать проблему в учебном окружении, а затем сравнить своё объяснение с ответом AI. В реальном инциденте, конечно, важнее быстро восстановить сервис.

Проверять нужно не знание Rust или Mongo, а способность поставить гипотезу, найти подтверждающие данные и оценить последствия изменения. Разработчик может пользоваться AI каждый день и хорошо понимать систему. А может читать код без AI и всё равно не понимать причин принятых решений.

Придётся поговорить с бизнесом о скорости

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

Поэтому я бы не продавал эту работу как «нам нужно разобраться с плохим AI-кодом». Для бизнеса важно другое: способна ли команда стабильно выпускать изменения, насколько вероятны серьёзные инциденты и сколько будет стоить их устранение.

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

У такого плана должны быть проверяемые результаты. Не «изучить MongoDB» и не «улучшить архитектуру», а подтвердить конкретные гарантии и снизить риски, которые уже удалось показать бизнесу. Это не повод превращать обучение в набор KPI, но так становится понятнее, за что компания платит. Такая работа потребует времени, а отсутствие честного разговора с бизнесом не отменит стоимость неизвестной системы, а лишь приведет к инцидентам и потерянным клиентам.

Когда проект всё-таки стоит переписать

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

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

При этом я бы не переписывал всё одновременно. Сначала нужно зафиксировать важное поведение, определить границы компонентов и по возможности менять реализацию постепенно. Иначе легко потерять часть бизнес-логики, о существовании которой команда узнает только после перехода. Критерий должен звучать не как «этот код написал AI» и даже не как «нам не нравится Rust». Вопрос в том, какую стоимость создаёт существующее решение и что действительно изменится после переписывания.

Почему систему дорого поддерживать?
├─ Не хватает тестов, наблюдаемости и процедур → стабилизировать систему
├─ Команда не знает технологический стек      → развивать компетенции
└─ Технология ограничивает развитие продукта  → планировать постепенную миграцию

Переписывание оправдано не происхождением кода, а ограничениями технологии, которые подтверждены на практике.

Как понять, что команда освоила проект

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

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

  • несколько инженеров способны объяснить, что произойдёт при отказе критической зависимости;

  • команда умеет безопасно изменить важный участок и проверить существующее поведение;

  • понятно, где искать причину ошибки в продакшене;

  • процедура восстановления проверена на практике;

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

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

Вывод

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

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

AI поможет восстановить документацию, написать тесты и объяснить незнакомую технологию, но способность команды самостоятельно принимать решения и отвечать за последствия изменений придётся выстраивать отдельно. Долг компетенций/понимания погашается не количеством сгенерированного кода или документов, а в тот момент, когда понимание системы перестаёт зависеть от одного человека или одного агента.

Автор: vovkats

Источник

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