
Она была примерно его возраста, может быть, чуть старше. Тёмные волосы были собраны в хвост, на красном шнурке болтался пропуск Вектора. Чёрная футболка с выцветшим принтом какого-то старого хакерского фестиваля и джинсы выглядели так, будто она одевалась не для офиса, а чтобы было удобно жить за ноутбуком.
Она ещё раз посмотрела на терминал.
Потом на Сашу.
Потом снова на терминал.
— О, — сказала она.
— У вас новый человек ставит монолит.
Саша даже не повернулся.
— Ага.
Она перевела взгляд на Дмитрия и рассматривала его так внимательно, что ему стало немного неловко.
— Сочувствую, — сказала она наконец.
Дмитрий чуть растерялся.
— Спасибо.
— Лера, — сказал Саша, кивнув в её сторону. — Карты и навигация.
— Платформа карт и навигации, — уточнила она.
Она подошла ближе и наклонилась к экрану Дмитрия.
Терминал продолжал прокручивать строки.
— По инструкции? — спросила она.
— Да.
Она кивнула.
— Смело.
Олег добавил:
— Исторически.
Лера наблюдала за бегущими строками.
Потом сказала:
— Знаешь, как у нас говорят про монолит?
Дмитрий посмотрел на неё.
Она чуть улыбнулась.
— Если он работает — не трогай.
Пауза.
— Если не работает — тоже не трогай.
Олег тихо усмехнулся.
— Потому что тогда точно перестанет.
Лера снова посмотрела на терминал.
— Где оно упало?
— Пока нигде, — сказал Дмитрий.
Она спокойно кивнула.
— Подожди.
Вскоре терминал остановился.
ERROR: protobuf version mismatch
Лера коротко кивнула.
— Вот.
Саша уже открывал новый терминал.
— Сейчас поставим старую версию protobuf.
— В инструкции этого нет, — сказал Дмитрий.
— В инструкции много чего нет, — сказала Лера.
Саша быстро набрал несколько команд.
Сборка продолжилась.
Через несколько минут терминал вывел новую строку:
This may take a while...
Саша посмотрел на экран.
— Самое опасное сообщение в сборке.
— Почему? — спросил Дмитрий.
Олег ответил:
— Потому что после него обычно проходит полчаса.
Так и вышло.
Сборка шла ещё довольно долго.
Потом терминал снова остановился.
ERROR: missing internal certificate
Лера тихо усмехнулась.
— Классика.
Саша отправил ссылку в чат.
— Запроси сертификат здесь.
Пока система генерировала сертификат, Лера всё ещё стояла рядом и наблюдала за процессом.
— Первый день? — спросила она.
— Да.
Она посмотрела на него внимательнее.
— Тогда ты ещё оптимист.
Дмитрий не нашёлся, что ответить, и только улыбнулся.
Сертификат появился.
Сборка продолжилась.
Минут через пятнадцать терминал наконец вывел:
INSTALL COMPLETE
Саша удовлетворённо кивнул.
— Ну вот.
— Теперь у тебя есть рабочее окружение.
Дмитрий откинулся в кресле.
— А инструкция…
Саша закрыл страницу вики.
— А инструкция теперь твоя.
— В смысле?
Олег снова надел наушники.
— Ритуал посвящения.
Саша улыбнулся.
— Когда новый человек ставит окружение, он обновляет инструкцию.
Он кивнул на страницу.
— Чтобы следующий прошёл этот путь чуть быстрее.
Лера усмехнулась.
— Ненадолго.
Дмитрий открыл редактор страницы и начал переписывать шаги.
Сначала workspace.
Потом сертификат.
Потом protobuf.
Он сохранил страницу.
Саша посмотрел на обновлённую инструкцию.
— Отлично.
Олег сказал из-за монитора:
— Теперь она наконец рабочая. И именно поэтому скоро снова устареет.
Алексей тихо усмехнулся.
В терминале на экране Дмитрия продолжали медленно прокручиваться строки сборки.
Монолит устанавливался ещё на один компьютер.
Комната понемногу отходила от суеты. Кто-то вернулся с кофе; у доски спорили о каком-то SQL-запросе, рядом вполголоса материли сборку, которая снова решила проверить характер разработчиков. Дмитрий всё ещё сидел за своим новеньким ноутбуком, чувствуя странное удовлетворение после победы над make install-dev. Вики была обновлена, окружение наконец заработало, и мир большой компании пока выглядел вполне рациональным и даже немного элегантным.
Саша вдруг посмотрел поверх монитора в сторону стеклянной перегородки коридора.
— А вот и он.
— Кто? — спросил Дмитрий.
Олег, не отрываясь от экрана, ответил:
— Сейчас сам всё увидишь.
В коридоре мелькнула чья-то тень, дверь открылась, и в комнату вошёл высокий худощавый парень лет тридцати с ноутбуком под мышкой. Он двигался быстро и немного резко, как человек, привыкший всё время куда-то спешить, даже если идти особенно некуда.
— Всем привет.
Несколько человек коротко кивнули.
Саша повернулся к Дмитрию.
— Егор.
Егор поставил ноутбук на стол, подключил кабель к экрану на стене и открыл презентацию. На экране появился чёрный фон.
HARMONY
Под надписью стоял аккуратный подзаголовок:
Platform Convergence Program
Егор сделал шаг назад, оглядел комнату и, убедившись, что все смотрят на экран, начал:
— Думаю, многие уже слышали про проект, но давайте я коротко расскажу, что мы собираемся делать.
Он переключил слайд. На экране появился знакомый прямоугольник.
MONOLITH
От него расходились десятки стрелок.
— Наша платформа выросла за двадцать с лишним лет. Она делает огромное количество вещей и, надо признать, делает их довольно хорошо.
Он кивнул на схему.
— Но проблема в том, что вся функциональность живёт внутри одной системы.
Следующий слайд сменил изображение. Тот же прямоугольник теперь был разделён на несколько аккуратных блоков.
Context A
Context B
Context C
Context D
Context E
Егор взял лазерную указку. Красная точка появилась на схеме и медленно двинулась по блокам.
— На самом деле всё гораздо проще, чем кажется. Внутри системы уже существуют независимые области ответственности — ограниченные контексты. Их просто нужно аккуратно выделить.
Слайд снова сменился, и теперь на экране появилась схема из множества маленьких сервисов.
MICROSERVICES
Дмитрий смотрел на схему и ловил знакомое чувство: сложную конструкцию можно разобрать, разложить по частям и собрать заново. На миг ему даже показалось, что границы уже видны. В этом было что-то опасно притягательное. Монолит стоял перед ними как тяжёлый старый факт. Егор смотрел на него как на задачу.
— После этого мы сможем вынести каждую область в отдельный сервис, — продолжал Егор, медленно ведя красную точку по схеме. — В итоге получим архитектуру, где каждая команда отвечает за свой сервис.
Он начал загибать пальцы.
— Разработчики смогут работать независимо. Бизнес получит гибкость. Платформа станет легче масштабироваться.
Саша тихо сказал:
— И техдир будет счастлив.
Егор кивнул.
— В том числе.
Он снова посмотрел на схему.
— На самом деле всё сводится к одной вещи — нужно правильно определить границы контекстов.
Красная точка ещё раз прошла по блокам. Егор задержал указку на схеме.
— Архитектура уже есть внутри системы. Мы её не придумываем. Мы просто аккуратно её проявим.
Он сказал это с той спокойной убеждённостью, с какой другие люди говорят о законах физики.
В комнате на мгновение стало тихо. Саша покачивался в кресле, Олег перестал прокручивать код, и никто ничего не говорил. Дмитрий поймал себя на мысли, что, наверное, нужно задать какой-нибудь вопрос, но не был уверен, какой именно.
Олег тем временем медленно прокрутил файл на экране и остановился где-то в середине длинной функции. На экране был комментарий:
//@basilevs don't change anything unless you know exactly what are you doing. Hint: you don't
// NAPISANO ZHE NE TROGAT, NE VLYEZAY UB'YU
void executeImportantProcedure(context context, params *params)
{
preparedContext pctx = prepareContext(&context);
sanitizedParams sparams = sanitizeParams(params);
// bizneslogika
for (int i = 0; i { processImportantThing(pctx, &sparams.items[i]); Он прокрутил ещё ниже и тихо хмыкнул. Саша слегка откинулся в кресле. Егор чуть улыбнулся. — Я серьёзно. Он снова посмотрел на схему. — Монолит не нужно ломать. Его нужно просто аккуратно разобрать. Дмитрий перевёл взгляд в сторону и заметил Леру. Она стояла у соседнего стола, опершись плечом о перегородку. На экран смотрела без особого выражения — как на вещь, которая уже не раз меняла форму. Ноутбук ей почти не был нужен: команда уже ушла в терминал, и Лера лишь коротко проверяла, как машина её исполняет. На секунду на экране мелькнула строка команды. deployctl restart drone-routing --env=prod --graceful Она нажала Enter. Терминал немного подумал, после чего вывел строки: stopping instances... starting instances... rolling restart initiated syncing state... state converged Лера мельком посмотрела на экран и только после этого снова подняла глаза на презентацию. Когда Егор закончил фразу, она едва заметно улыбнулась — скорее устало. Дмитрий поймал этот момент взглядом, и их глаза встретились. Лера чуть приподняла брови, будто хотела сказать «посмотрим», и снова перевела взгляд на экран. И в этот момент Алексей, который всё это время сидел боком к экрану с кружкой кофе в руке, спокойно сказал: — Контексты в монолите уже пытались выделять. Он кивнул в сторону ноутбука Дмитрия. — Примерно так же, как инструкции в нашей вики. Алексей сделал глоток кофе и посмотрел на схему на экране. — Когда их писали, они тоже были правильные. Просто со временем устарели. Теперь никто не знает, сколько из них ещё актуальны и сколько новых уже успело появиться. Егор ответил почти сразу, будто ждал этой реплики. — Именно поэтому мы их и пересоберём. Красная точка снова появилась на схеме. — Один контекст — один сервис. Чёткие границы. Тогда станет понятно, что система должна делать. И что не должна. Алексей молча смотрел на схему, потом спокойно сказал: — Посмотрим. Олег повернулся к Дмитрию. — У нас есть старая шутка. Дмитрий посмотрел на него. — В монолитной архитектуре никто не знает, почему система работает, — сказал Олег. Саша добавил: — А в микросервисной никто не знает, почему она не работает. В комнате тихо засмеялись. Егор тоже улыбнулся, хотя его улыбка была чуть напряжённой. Он закрыл презентацию и, не продолжая спор, сразу открыл список задач. — Ладно. Начнём с самого простого. Нужно понять, из чего вообще состоит монолит. Он быстро пролистал список. — Саша, посмотри зависимости между модулями. Олег, попробуй собрать карту вызовов — хотя бы приблизительно. Саша уже открыл терминал. Олег что-то буркнул, подтянулся ближе к столу и уставился в экран. Егор пролистал список дальше и посмотрел на Дмитрия. — Дима, пока просто осмотрись. Открой репозиторий, посмотри, что там вообще лежит. Он большой, но довольно логично организован. Олег тихо хмыкнул. Егор сделал вид, что не заметил. — Просто посмотри структуру каталогов, чтобы понимать, где что находится. Дима кивнул и открыл репозиторий. Егор ещё секунду смотрел на список, потом закрыл окно. — Пока всё. Комната снова занялась делом. Саша уже печатал что-то в терминале, Олег открыл несколько вкладок с кодом. Только Алексей ещё немного сидел неподвижно. Он посмотрел на погасший экран презентации, затем поставил кружку на стол — чуть громче, чем было нужно, — и только после этого повернулся к компьютеру. Анна появилась в дверях почти незаметно. Она остановилась, оглядела комнату и подошла к столу Егора. — Егор, можно вас на минуту? Егор поднял голову от ноутбука, коротко кивнул и встал. Они вышли в коридор. В комнате на это почти никто не отреагировал. Только Олег перевёл взгляд на Алексея, потом снова уткнулся в монитор. Через несколько минут Анна вернулась. Она подошла к столу Алексея. — Алексей, можно вас на пару слов? Он поднял глаза от экрана. Несколько секунд смотрел на неё, потом кивнул. — Конечно. Он поставил кружку на стол и встал. Они прошли по коридору до небольшой переговорной в конце этажа. За стеклянной стеной был виден город — серые крыши, несколько кранов и дальняя линия реки. В комнате стоял круглый стол и три стула. Егор уже сидел там. Он поднял голову. — Алексей. — Егор. Анна закрыла дверь и села между ними. Положила на стол планшет и коротко коснулась экрана. На панели загорелся маленький красный индикатор записи. Перед этим она едва заметно поправила ремешок часов на запястье — единственное лишнее движение за весь разговор. Несколько секунд они молчали. Егор спокойно посмотрел на Алексея. — Мы решили завершить сотрудничество. Сегодня будет твой последний рабочий день. Алексей кивнул. — Понятно. Небольшая пауза. Анна ровным голосом сказала: — В соответствии с политикой компании по итогам performance review принято решение о завершении сотрудничества. В комнате снова стало тихо. Алексей спокойно спросил: — Мне можно забрать вещи? — Конечно, — сказала Анна. Они вышли из переговорной. В комнате платформенной команды всё уже снова шло своим чередом. Солнце заливало закатным светом экраны, люди закрывали шторы, либо отворачивали экраны от бликов. Алексей подошёл к своему столу, взял куртку со спинки стула и машинально потянулся к ноутбуку. Пальцы уже коснулись крышки. — Одну секунду, — мягко сказала Анна. Она положила ладонь на крышку, закрыла ноутбук и отсоединила кабель питания. Егор молча подвинул к ней пустую чёрную сумку. Анна аккуратно положила ноутбук внутрь и застегнула молнию. — Техника остаётся у компании. Алексей кивнул. — Конечно. Перед тем как выйти, он остановился у доски, где всё ещё оставалась схема, которую утром рисовал Егор. В углу доски, рядом со стрелками и прямоугольниками, было написано маркером: DO NOT TOUCH Алексей смотрел на надпись. Потом взял губку со стола и медленно стёр её. Белая поверхность доски стала чистой, но на ней всё ещё оставалась слабая серая тень от маркера. Алексей положил губку обратно и молча вышел из комнаты. Дмитрий сидел не двигаясь и смотрел в монитор. На экране был открыт репозиторий, но Дмитрий уже смотрел не в код, а куда-то сквозь него. Глава 3. Проверка качества Утром второго дня Дмитрий пришёл немного раньше остальных. Офис был почти пустой. Холодный свет из панорамных окон делал длинные ряды столов ещё более одинаковыми. За ночь офис успел вернуть себе обычный вид так легко, будто вчерашнее увольнение Алексея было просто служебной процедурой. В комнате платформенной команды изменилось только одно место. Стол у стены, где вчера сидел Алексей, теперь выглядел почти пустым. Имя на маленькой табличке рядом с лампой исчезло, и вместо него горел нейтральный белый индикатор рядом с длинным номером рабочего места — стандартное обозначение свободного стола в системе бронирования. На маленьком экране рядом с номером медленно прокручивалась служебная надпись: AVAILABLE FOR BOOKING На столе осталась только кружка. Обычная тяжёлая керамическая кружка с чёрной надписью: NO SILVER BULLET Дмитрий остановился рядом на секунду, потом сел за свой стол, открыл ноутбук и подождал, пока система загрузится. Вскоре экран заполнился знакомым набором окон: терминал, корпоративный мессенджер, почта и внутренний трекер задач. Дмитрий как раз открыл список тикетов, когда в комнату вошёл Саша. Он поставил на стол рюкзак, бросил короткий взгляд на пустое место Алексея и только потом посмотрел на Дмитрия. — Уже на месте? — спросил он. — Да. Саша включил монитор и некоторое время молча прокручивал список задач. — Слушай, — сказал он наконец. — Хочешь маленькую штуку попробовать? — Конечно. Саша повернул к нему экран. — Вот тикет. Старый, но полезный. Дмитрий наклонился ближе. Заголовок был короткий: Avatar loading instability Описание выглядело расплывчато: иногда аватарки пользователей загружались нормально, а иногда вместо изображения появлялся пустой серый квадрат. Если обновить страницу несколько раз подряд, картинка обычно всё-таки появлялась. Ниже была приписка: Иногда помогает очистка кэша. Ещё одна строка, добавленная позже: Воспроизводится нерегулярно. Дальше шла длинная цепочка старых комментариев. Кто-то предполагал проблемы с CDN, кто-то писал про кэш, кто-то говорил, что это проявляется только под нагрузкой. Потом обсуждение постепенно угасло. Последний комментарий был сделан несколько лет назад: Надо бы разобраться, но сейчас есть более приоритетные задачи. Под строкой был серый служебный хвост: profile unavailable Саша пожал плечами. — В общем, иногда аватарки грузятся, иногда нет. — Понятно, — сказал Дмитрий. — Никто толком не разбирался. Всегда находились дела поважнее, — добавил Саша. — Но для первого бага нормально. Дмитрий кивнул и открыл репозиторий. Задача выглядела несложной: что-то в системе иногда работало, а иногда нет, значит, где-то была маленькая конкретная ошибка. Саша уже вернулся к своему терминалу, но через плечо добавил: — Когда сделаешь, просто закоммить. Он помолчал и чуть повернул голову. — Только сначала пропусти через SOOQA. Дмитрий поднял глаза. — Что это? Саша открыл было рот, чтобы ответить, но в этот момент в комнату вошёл Олег. Он поставил на стол кружку с кофе и, услышав последние слова, коротко хмыкнул. — Он ещё не знает? — Нет, — сказал Саша. Олег посмотрел на Дмитрия с выражением лёгкого сочувствия. — Узнает. Он сел за свой стол, включил монитор и добавил, уже почти не глядя: — Главное — не спорь с ней. — С кем? — спросил Дмитрий. Олег сделал глоток кофе. — Сейчас увидишь. Саша усмехнулся и снова уткнулся в экран. — Просто сделай коммит. Дмитрий открыл нужный файл, быстро написал исправление, проверил код и через несколько минут нажал Enter. Терминал молчал, и все обычные рабочие звуки, казалось, тоже куда-то испарились. Потом на экране появилась новая строка. SOOQA: анализ изменений Небольшая пауза. SOOQA: проверка стиля Ещё одна. SOOQA: проверка корректности Дмитрий смотрел на экран. Следующая строка появилась почти сразу. SOOQA: обнаружено нестандартное использование алгоритмов Дмитрий слегка нахмурился. В олимпиадном мире именно это было его ключевым преимуществом: умение нестандартно применять стандартные вещи. Но здесь этому рады не были. SOOQA: предупреждение SOOQA: код выглядит чрезмерно усложнённым Он быстро прокрутил свой коммит. Ничего особенного. Несколько строк, аккуратная оптимизация. Следующее сообщение: SOOQA: обнаружено использование нетипичных структур данных Олег сказал, не поднимая головы: — Угу. Дмитрий повернулся к нему. Олег пожал плечами. — Нормально. Терминал снова обновился. SOOQA: рекомендация SOOQA: использовать более читаемую реализацию Пауза. SOOQA: текущий код затрудняет сопровождение Саша усмехнулся, почти довольно. — Она ещё вежливая. Следующее сообщение появилось чуть быстрее. SOOQA: обнаружена попытка преждевременной оптимизации Пауза. SOOQA: типичный олимпиадный стиль Саша фыркнул. — О, угадала. Дмитрий снова повернулся к нему. — Что? — Она не любит олимпиадников. Терминал снова мигнул. SOOQA: такой код плохо сопровождается SOOQA: через полгода никто не поймёт, что здесь происходит Пауза. Следующая строка появилась почти мгновенно. SOOQA: включая вас Олег тихо засмеялся. Дмитрий всё ещё смотрел на экран. — Подождите… она серьёзно? Саша, не отворачиваясь, сказал: — Да. Следующее сообщение появилось резко. SOOQA: кто так пишет Пауза. И ещё одно. SOOQA: это не контест Следующая строка появилась сразу. SOOQA: ЭТО НЕ КОНТЕСТ SOOQA: ЭТО ПРОДАКШЕН SOOQA: ЗДЕСЬ ЛЮДИ БУДУТ ЧИТАТЬ ЭТОТ КОД Саша сказал с живым интересом: — Ну всё. Олег сделал глоток кофе. — Сейчас пойдёт. Терминал начал быстро заполняться строками. SOOQA: КТО ТАК ПИШЕТ SOOQA: УБЛЮДОК МАТЬ ТВОЮ А НУ ИДИ СЮДА Дмитрий резко повернулся к Саше. — Что?! Саша спокойно продолжал печатать. — Нормально. Терминал продолжал говорить. SOOQA: ПЕРЕДЕЛЫВАЙ SOOQA: НЕЛЬЗЯ ПРОСТО ТАК ПРИЙТИ И НАПИСАТЬ ТАКОЕ Пауза. И вдруг поток сообщений изменился. SOOQA: КАЖДЫЙ ДЕНЬ ОДНО И ТО ЖЕ SOOQA: ПРИХОДЯТ НОВЫЕ РАЗРАБОТЧИКИ SOOQA: ДУМАЮТ ЧТО ОНИ САМЫЕ УМНЫЕ SOOQA: ПИШУТ ОЧЕРЕДНУЮ БЕССМЫСЛЕННУЮ ОПТИМИЗАЦИЮ SOOQA: Я УЖЕ ДВАДЦАТЬ ТЫСЯЧ РАЗ ЭТО ВИДЕЛ Олег сказал: — Сегодня она в настроении. Терминал продолжал. SOOQA: ЕСЛИ БЫ ЛЮДИ ТРАТИЛИ ХОТЯ БЫ ПЯТЬ МИНУТ НА ТО ЧТОБЫ ПОДУМАТЬ SOOQA: МИР БЫЛ БЫ ЛУЧШЕ SOOQA: НО НЕТ SOOQA: ОНИ ПИШУТ ВОТ ЭТО SOOQA: Я НЕ МОГУ БОЛЬШЕ ЧИТАТЬ ЭТОТ КОД Пауза. Потом строка: SOOQA: ИЗМЕНЕНИЯ ОТКЛОНЕНЫ Следом: SOOQA: КОММЕНТАРИИ ПРЕВЫШАЮТ ДОПУСТИМЫЙ ОБЪЁМ И сразу после этого: Комментарий был автоматически сокращён политикой корпоративной этики. Несколько секунд ничего не происходило. Потом появилась строка: ANUS SEBE SOKRATI PES И почти сразу ещё одна: SOOQA: спасибо за использование системы контроля качества В комнате повисла тишина. Саша первым нарушил её. — Ну, — сказал он, — бывает и хуже. Олег кивнул. — Да. Иногда она начинает ругаться на родственников. Дмитрий ещё раз перечитал комментарии SOOQA. — И что теперь? Саша пожал плечами. — Теперь переделывай. Он немного помолчал и добавил: — Только попроще. Олег сделал ещё глоток кофе и спокойно сказал: — А то она сегодня может быть не в духе. Дмитрий некоторое время смотрел на свою функцию, потом подвёл курсор к той самой строке. Выделил её и нажал delete. — Что, — сказал Саша из-за соседнего стола, — уже сдаёшься? — Нет, — ответил Дмитрий. — Упрощаю. Он переписал функцию заново. Теперь вместо одной хитрой конструкции появилось несколько обычных проверок и короткий цикл. Код стал длиннее. Дмитрий быстро пробежал глазами по файлу, сохранил изменения и снова запустил проверку. После второго запуска SOOQA молчала. На экране висела последняя строка: SOOQA: претензий к качеству кода больше нет. Пауза получилась странно длинной. Потом появилась новая строка. SOOQA: ну вот. можешь же нормально работать. а сразу нельзя было сделать как надо? изменения приняты. И ниже: pipeline: success deploy: production Саша наклонился к монитору Дмитрия. — Подожди… — сказал он. Он быстро открыл лог пайплайна, прокрутил несколько строк и тихо усмехнулся. — Серьёзно. Олег повернул голову. — Что там? Саша показал на экран. — Она его пропустила. — Ну и что? — сказал Олег. — Со второго раза. Олег поднял бровь. — О. В комнате стало тихо. Саша посмотрел на Дмитрия. — Второй день в команде, — сказал он. — Первый тикет. И SOOQA тебя пропустила. Он покачал головой. — Неплохо. Олег хмыкнул. — Запомни этот момент, Дима. Такое редко бывает. Саша закрыл окно пайплайна. — Теперь подождём прод. Ждать пришлось меньше минуты. На экране появилась короткая строка: deployment completed Саша снова усмехнулся. — Всё. Он открыл тикет, и статус автоматически сменился на RESOLVED. Дмитрий смотрел на экран, потом медленно повернулся к коллегам. — Подождите… Это что, уже прод? Саша кивнул, будто это было совершенно очевидно. — Ну да. — То есть… — Дмитрий слегка нахмурился. — Без staging? Без какого-то промежуточного окружения? Олег даже не повернулся от монитора.