Что делать, если через пару месяцев аутсорс-команда исчезнет, а проект с кодом, который вы видите впервые в жизни, целиком остаётся на вас? История и маленькие практические советы по выживанию от разработчика — для команд, которым предстоит забирать проект в условиях отсутствия документации, и для тех, кто внезапно оказался за это ответственным.

Предыстория: когда с аутсорсом что-то пошло не так

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

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

Вводные данные: проект и личные ожидания (которые не оправдались)

Кто, собственно, я — Java-разработчик сервиса «Майснаб» и тот человек, которому поручили этим заниматься. На тот момент — без опыта руководства командой, но с опытом менторства; без опыта построения архитектуры на глобальном уровне (и вообще не с супербольшим опытом коммерческой разработки, раз уж на то пошло), но с интересом и желанием в этом преисполниться. 

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

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

Проект, которым нужно было заниматься: микросервисы (аж 21 штука), тоже на Java (и на том спасибо), в стадии развёрнутого и достаточно жизнеспособного MVP. Тестирование уже переехало к нам, и планировалось (по крайней мере, в моей голове), что мы с ещё одним разработчиком где-то полгодика поработаем под менторством аутсорс-команды: они будут принимать важные решения и разбираться с проблемами, а мы — постепенно привыкать к новой системе. А потом, когда-нибудь, когда мы почувствуем себя готовыми, случится передача ответственности…

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

Этап номер один (первый провал)

Итак, двадцать один новый сервис, ноль документации, очереди сообщений, распределённые транзакции, угрожающе выглядящие таблицы в реляционной БД, которые почему-то не в 3НФ, два разработчика, которые всё это видели только в статьях и pet-проектах — и осознание, что в скором времени сторонняя команда уйдёт, а разбираться со всеми бизнесовыми хотелками, клиентскими проблемами и падениями прода придётся только нам. При этом аутсорс-коллеги уже что-то там спроектировали, заложили какие-то абстракции на будущее — и это тоже не хотелось бы сломать… 

Так родилась первая паническая идея: «до начала активной разработки осознать всё, что только можно, чтобы быть готовыми ко всему».

Вот наш примерный список вопросов — от экзистенциальных до вполне прикладных, которые возникли в процессе поиска ответов на экзистенциальные:

  • Как всё это дело развернуть? Сколько стендов и зачем они? Какие на стендах стоят ветки? А что по стратегии ветвления?

  • Что будет, если сервис упадёт? Как организован мониторинг? Где смотреть логи? А есть ли у kafka какие-то логи? Как её мониторить? Что будет, если kafka упадет? А почему вообще именно kafka?

  • Как сервисы общаются между собой? Почему где-то HTTP-запросы, а где-то очереди сообщений? Почему где-то обновление данных между сервисами идёт напрямую, а где-то — через saga orchestration?

  • Какие компоненты есть внутри сервиса? Есть ли конвенции, которым нужно следовать? Почему почти везде есть интерфейсы, но где-то их нет?

  • Почему у нас postgres, но в каждом сервисе — по одной таблице, а бизнесовые данные лежат в одном jsonb-поле (этот вопрос мучил меня больше всего!!)? Если мне нужно сделать запрос к глубоко вложенному в этот jsonb полю — как я это буду делать?

В общем, мы со вторым разработчиком раскидали этот список между собой, начали собирать информацию, читать код, документировать, и…

Диалог:

– Есть, может, какая-то инструкция, которую вы рассылаете своим новеньким, чтобы они разобрались?

– К сожалению, нет, только на словах... Давай конкретные вопросы. 

Задаю вопросы.

Каждый раз по ситуации... По этому процессу вообще полное творчество, так как ничего не описано нигде. Второй вопрос на целый доклад. Тоже все по ситуации, на самом деле… Третий – вообще доклада на 3...

Что-то, конечно, выяснилось — стенды и ветки, например (здесь ничего не могло пойти не так), но когда мы полезли в код, стало понятно, что: 

а) абстрактные вопросы порождают абстрактные же ответы (посмотрим на диалог выше), и всегда имеют место истории «так сделано на нашем другом проекте, скопировали оттуда» или «тут решение на скорую руку, планировали переделать, когда будет время»;

б) простые прикладные штуки, во-первых, достаточно быстро гуглятся, а во-вторых, мгновенно стираются из памяти, как только ты перестаешь их активно использовать (вспомним мемы про senior developer Google search). 

Этап номер два (успех)

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

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

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

Первое — больше задач! 

Очевидный совет номер один — делать задачи. Как можно больше задач, хороших и разных, особенно если они:  

а) из мерзкого техдолга, до которого ни у кого из аутсорс команды не доходили руки;

б) касаются новых для нас областей (в нашем случае — всё, связанное с микросервисами).

Примеры задач, выполненных мной, с описанием, почему это было полезно:

  • Перезаписать в DTO с фронта одно поле на значение из базы, чтобы его точно не затерли. Одна строчка, но зато обновление шло через местную реализацию Saga Orchestration, так что получилось ее подебажить.

  • Рефакторинг (который, честно говоря, я уже толком не помню) чего-то затрагивающего общую на все сервисы абстракцию в кастомной проектной библиотеке. Помог разобраться с версионностью + пришлось залезть в N сервисов + посмотреть, что там в этой библиотеке есть.

  • Сделать сервис фонового обновления данных для текстового поиска, чтобы можно было искать в одном сервисе по данным, принадлежащим доменным моделям других сервисов. Например, в сервисе счетов, где есть только uuid автора + строчка с его ФИО на момент сохранения счета, искать по актуальным на текущий момент ФИО автора этого счета, информация о которых хранится в сервисе пользователей. Тут получилось словить комбо: очереди и асинхронную обработку, а главное – проблемы с несогласованностью данных, когда сообщение в очередь уже улетело и триггернуло сервис, который попытался запросить данные из другого сервиса, а у другого все еще не завершилась транзакция, и актуальных данных в базе еще нет

    Второе — ревью

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

    Диалог 2:

    – Скидываю ссылку на merge request

    – Давай я тебе вопрос задам без ответа и ты сразу коммиты поправишь? Допустим, мы убрали поисковую информацию из всех сервисов и засунули в эластик, будет работать? И сколько надо изменений? Блин, два вопроса получилось…

    Диалог 3:

    – … нагрузка в месседже может быть для каждого события своя, апи от нее зависеть не должно, просто сейчас как-то все обошлось очень похожей нагрузкой.

    – Это будет полный роллбэк сейчас, я так понимаю…

    – )))

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

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

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

    Третье — расследование инцидентов

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

 

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

  1. Если прод ведёт себя странно — начинаешь расследование. Получилось разобраться — супер. 

  2. Если не получилось — идёшь к аутсорс-разработчику, спрашиваешь, куда смотреть: в какие метрики, в какие логи, в какой сервис.

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

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

Что было дальше:

Через три с половиной месяца мы остались одни, но уже без паники, с надеждой на светлое будущее. Вселенная не cхлопнулась. Это достаточно короткий срок для такого масштабного переезда в условиях нашего ограниченного опыта, так что в первое время все еще было страшно что-то поломать или в чем-то не разобраться… Но постепенно у нас получилось перейти от состояния «боюсь тронуть» и «хоть бы не навернулось» к крупным переделкам и оперативному решению проблем без лишней суеты. Сервисов у нас, кстати, теперь на четыре больше.

Теоретически, у нас осталась возможность задать вопрос бывшей команде, но на практике стратегия «задать вопрос потом» тоже не самая рабочая, потому что:

а) спрашивать о чем-то мелком не имеет смысла — люди довольно быстро выпадают из контекста (кто может детально описать ход своих мыслей в контексте прошлогодней задачи – пусть первым кинет в меня камень);

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

Выводы

  1. Забрать себе проект c аутсорса — реально, даже если это нужно сделать быстро, даже если он «другой» и релевантного опыта у вас немного.

  2. Теория — хорошо, но без практики не работает. Плюс есть риск зарыться в поиске причин и правил, которых нет.

  3. Брать сложные мерзкие задачи и расследовать сложные мерзкие проблемы — лучший способ ускорить погружение.

  4. Если есть возможность поработать с людьми, которые проект писали –– супер! Но на время придется вырубить свою интровертность и задавать вопросы. Очень много вопросов.

  5. Вы во всем разберётесь. Со временем. 

Комментарии (1)


  1. titulusdesiderio
    15.07.2025 19:53

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

    Кстати, а сейчас вы уже покрыли его документацией?