Предыстория

Nexign (ex. Петер-Сервис)

С 2019 года занимался проектированием и реализацией инфраструктурного компонента биллинг-контура, который являлся «enabler‑ом» bpm‑сценариев, написанных на apache camel. Из технологий: микросервисная архитектура на Java + Spring + Akka Actors, в качестве базы данных использовали Oracle + PL/SQL для чистки партиций, брокер rabbitmq. Проектировали в терминах DDD, Event Sourcing. Система обслуживала биллинг мобильного оператора «Мегафон».

Yandex FinTech

В феврале 2022 года мой близкий знакомый, уже работавший в инфраструктурной команде Яндекс Финтеха, убедил меня попробовать свои силы в доменной области финансовых организаций и рефнул меня. Подготовившись к алгоритмическим секциям через прорешивание задачек из раздела «yandex» на leetcode, я отправился проходить секции. Было два этапа алгоритмов и один этап архитектурной секции. В результате, чуть поторговавшись относительно грейда, который мне присуждают, меня приняли на работу в команду клиентского досье, где я участвовал в разработке сервисов для хранения и проверки персональных данных клиентов банка, а также идентификации новых клиентов через портал «Госуслуги». Параллельно с работой над клиентским досье переключался в трек «Логистической платформы», где допилил текущее состояние кодовой базы до тестового запуска и внедрения в эксплуатацию базовых сценариев заказа пластика/документов на подписание через контрагента в лице логистической компании. Из технологий: микросервисы на kotlin + spring boot + очередь stq для async запуска bpm‑сценариев, в качестве баз данных использовали Postgresql и YDB.

Ozon ML Infrastructure

Приняв участие в разработке ядра финтеха, я начал испытывать симптомы выгорания и принял решение взять таймаут с целью осознать причины и предпринять шаги по устранению возникшей проблемы. В результате: июнь 2024 года — общаюсь с рекрутерами Ozon в качестве кандидата в команду ML-инфраструктуры. Успешно прохожу coding‑секции, где мне было предложено проанализировать и порефакторить функции service‑layer кода микросервиса, который ходил в репозиторий и доставал какие‑то данные. Приняли в команду, выдали ноутбук, отправили пилить платформу для инференса и обучения ML‑моделей. Удалось проработать недолго — 7 месяцев. Наибольший импакт заключался в интеграции интерфейса Apache Spark в ядро платформы, что позволило запускать батчевые задачи по обучению моделей на мощностях инфрового кластера в облаке для смежной команды DS‑ов. Из технологий: микросервисы на kotlin + spring boot, база данных postgres. И тут случилось неожиданное: симптомы выгорания вернулись. Стало очевидно, что проблему я не победил до конца и простого перерыва оказалось недостаточно. Пообщавшись с менеджером команды и сотрудником HR‑отдела, я принял решение приостановить сотрудничество и пошел искать другой подход к сложившимся обстоятельствам.

Поиск работы в 2025

Итак, осень 2025. Полон сил и решимости завершить трек с выгоранием и наконец-то вернуться в стезю консистентного перформанса.

Подходы, которые применял в этот раз:
1. Обратился к терапевту: пропил курс антидепрессантов;
2. Уменьшил количество когнитивной нагрузки на определенный промежуток времени;
3. Завел семью :)

Попытка № 1

С конца лета я активно откликался на вакансии, размещенные на hh.ru. Из регионов выбирал Москву и Петербург, формат — удаленный/гибрид. К моему удивлению, большой активности со стороны рекрутеров обнаружить не удалось. Однако в сентябре ко мне пришла команда рекрутмента VK со списком интересных вакантных позиций.

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

  1. Сортируем отрезки [(x1,y1), (x2,y2) ..., (xn,yn)] с целью упорядочить и в дальнейшем определить их вхождение друг в друга(для сжатия);

  2. Итерируемся по отсортированному массиву, собирая новую коллекцию (важно проверять, не входит ли текущий отрезок из массива в последний «сжатый» отрезок в целевой коллекции, если входит, то мержим текущий в последний «сжатый отрезок»);

  3. Переопределяем метод toString() у класса-контейнера для сжатых отрезков и реализуем сериализацию в строковое представление, как того требует исходное условие;

  4. Преобразуем коллекцию в набор строк и собираем результирующую строку с помощью StringBuilder;

  5. Наконец-то возвращаем получившуюся строку, которая представляет из себя набор сжатых отрезков в строковом представлении.

  6. Оценка сложности алгоритма по времени: используем сортировку, встроенную в java библиотеку -- quicksort. Сложность O(n log n) в среднем, в худшем O(n^2).

В результате оценки написанного кода на Java (кстати, хотел писать на Kotlin, так как к Java не прикасался со времен первого проекта в Nexign, однако получил отказ и выдал код на требуемом языке) интервьюер обнаружил один пропущенный мною корнер‑кейс в цикле, который формирует промежуточную коллекцию «сжатых» отрезков. В ответ на что я дописал пропущенный if-ок. И со словами интервьюера «Так, ну я посмотрел, тут вроде все ок по коду» мы перешли к этапу общения на тему теоретических нюансов jvm‑платформы. Нужно отметить, что поиск решения и написание кода заняло львиную долю интервью (40-50 минут) и на дополнительные вопросы осталось не так много времени.

Интервьюер задал следующие вопросы (из тех, которые помню):
1. Что такое отношение happens-before?
Мой ответ: В современных архитектурах события, порождаемые кодом, могут происходит не в строгой последовательности относительно написанных строчек кода (отсылка к reordering). Привел классический пример в терминах Event A, Event B.
2. Как достичь соблюдения отношения happens-before?
Мой ответ: один из подходов — использовать примитивы и структуры данных для синхронизации.
3. Какие примитивы и структуры для синхронизации знаешь?
Мой ответ: упомянул synchronized блоки и реализации из java.util.concurrent: CyclicBarrier, CountDownLatch и т. д.

На этом интервьюер прервал собеседование, сославшись на истекшее время.

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

Попытка № 2

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

Итак, продолжаю откликаться на вакансии на hh.ru, параллельно изредка решая задачки на leetcode‑e, используя Java. Трек поиска работы на hh.ru до сих пор показывает слабую активность. Резюме просматривают компании из топа Российского IT, однако личка пуста. Реакция на мои отклики — слабая: либо отказ, либо просмотрено.

Алгоритмическая секция (1 час)

И вот, спустя месяц после предыдущей попытки снова вижу сообщения от рекрутера VK со списком вакансии в «Единые облачные технологии» на позицию ведущего разработчика и просто java‑разработчика. Соглашаюсь на созвон с HR‑специалистом. Рекрутер форвардит меня на свою коллегу. Созваниваемся в зуме (звонок через сам vk не завелся (: ). Общаемся относительно моего опыта и про бенефиты, которые компания предоставляет сотрудникам, и про предстоящий процесс найма, если я заинтересуюсь — одна алго‑секция, livecode‑секция и финал. Также было предложено пройти весь флоу за выходные, поставив две секции на один день. Я отвечаю: «Дайте подумать, давайте свяжемся в течение дня — двух». Решаю, что ставить две секции на один день с учетом перерыва — так себе идея. Назначаю секции на будние дни с промежутком в сутки. В ответ — список типовых задач на leetcode, которые полезно порешать, чем, собственно, и занимаюсь в период перед первым этапом.

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

1. Заводим мапу для сопоставления «символ → размер самого длинного окна».

2. Заводим счетчик для подсчета длины текущего окна, а также переменную, хранящую текущий символ текущего окна.

3. Пробегаем по строчке. Считаем длины окон повторяющихся символов, агрегируем подсчеты в мапе из п.1 (важно хранить только максимальные длины окон).

4. После итерации по символам строки не забываем учесть последние данные.

5. Возвращаем мапу, состоящую из отображения символа на максимальную длину окна.

Интервьюер задает пару уточняющих вопросов относительно реализации: например, спрашивает про иммутабельные коллекции и почему было бы здорово обернуть в ImmutableMap. Затем начинает гонять по теории коллекций в Java. Спрашивает о коллекциях, которые я знаю. Рассказ про коллекции разделяю на три основных «типа»: массивы, списки, деревья. Рассказываю про нюансы реализации HashMap. Отвечаю на вопрос о том, какое количество бакетов выделяется изначально при создании инстанса HashMap — 16. Рассказываю о функции хеширования, которая позволяет определять конкретный бакет в HashMap при выполнении той или иной операции. Вспоминаю про коэффициент заполняемости и политику расширения выделенной памяти в соответствии с этим коэффициентом. Затем обсуждаем подходы к написанию многопоточных систем — делаю краткий обзор паттерна ExecutorService. Отвечаю на вопрос, почему ExecutorService предпочтительнее создания потока в лоб. На этом интервью подходит к концу. В рамках этой попытки мне удалось решить задачу сильно быстрее(~30 минут) и ответить на большее кол‑во вопросов.

Live-code секция (1 час 30 минут)

HR‑специалист возвращается в тот же день с положительным фидбеком. Назначаю вторую секцию с livecode через день. В качестве подготовки собрал gradle‑проект на spring boot и реализовал простенький user service с базовым REST и шедулером для проверки клиентов по крону. Написал несколько интеграционных тестов на ручки (с h2 под капотом в качестве БД).

Итак, вторая секция. Пришел интервьюер, принес gradle проект в zip-ке. Скинул через чат в зум. Я развернул проект, прочитал readme.md, в котором просили реализовать сервис умеющий:

1. Сохранять события «кликов» на посты в ленте;

2. Агрегировать список авторов постов, на которые происходили клики пользователей за предыдущие сутки с фильтрацией авторов по переданому на вход множеству;

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

По сути, в задаче требовалось реализовать индекс по событиям с двумя операциями: положи в индекс событие клика (с уточнением времени события с точностью до суток) и вытащи события за вчерашний день с фильтрацией по множеству авторов, которые передаются на вход. Разделил реализацию на три уровня: контроллер с двумя методами (стаб уже был в проекте, осталось написать только реализацию методов), сервисный слой, состоящий из EventService, который, в свою очередь, реализовывал метод store(Event): void и aggregate(Set<Integer>): Set<Integer> и слой репозитория, инкапсулирующий магию построения индекса. Также ввел разделение на request/response модель и доменную модель сущности Event. Отдельную data-модель городить не стал, т.к. хотелось сэкономить время. В итоге реализовал слой репозитория через структуру Map<Instant, Map<Integer, Set<Integer>>>. События попадали в репозиторий, проходя через EventMappe , который, в свою очередь, округлял время события до дня. Таким образом, получилось, что индекс состоит из партиций размером в день, куда попадают события, которые, в свою очередь, раскладываются по author_id и user_id в мапу, ассоциировавшую id автора c множеством id пользователей, кликнувших на публикацию. Где-то в этот момент интервьюер напомнил, что осталось 20 - 25 минут и пора бы писать тесты, а я все еще добивал доменную логику сервиса. Перешли к тестам. Удалось успеть написать только один тест на EventService, который проверяет условие, что после добавления сегодняшних событий сервис возвращает пустое множество (т.к. за вчера событий не было) и отловить баг в самом тесте (забыл отмаппить событие через EventMapper перед передачей в сервис). Время подошло к концу.

Финальное интервью (40 минут)

На вторые сутки после livecode секции приходит HR и говорит, что интервью прошло успешно. Приглашают на финал с руководством поисковых вертикалей. Прихожу на финал, а там два руководителя направления рекомендаций и HR-специалист. Просят рассказать про предыдущий опыт. Я вкратце пробегаюсь по своим проектам, начиная с первого и заканчивая ML-инфрой Ozon. Затем начинается подробный допрос относительно логики и семантики ручек логистических сервисов Финтеха. Дальше рассказывают о себе. Намекают на то, что мы очень продуктивные и «не вынимаем», так сказать. Озвучивают «консёрн» относительно моего выгорания и моей способности «попасть в струю». Занавес!

На следующий день приходит HR‑специалист и говорит: «К сожалению, решили не продолжать процесс твоего найма». Думаю — ок, а что с остальными вакансиями, которые мне предлагались, и которые, собственно, меня заинтересовали. Пишу рекрутеру, который изначально пришел ко мне и пригласил попытать свои силы в «Единые облачные технологии». Спрашиваю, а будет ли возможность попробовать себя, собственно, по вакансиям, которые меня изначально заинтересовали («А то я тут обнаружил себя на финал в команду поисковых вертикалей...»). В ответ — по результатам технических секций мы приняли решение не продолжать сотрудничество. И вот тут я совсем ничего не понял. Т.е. по результатам технических секций день назад вы готовы были пригласить меня на финал в поисковые вертикали, а сегодня используете формулировку, которая указывает на недостаточно хорошее прохождение этапов.

Спасибо за внимание! Продолжаем поиски!

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


  1. Tzimie
    22.10.2025 10:23

    А на что вы кушали с 2022 года по 2025? Я тоже так хочу выгореть


    1. urvanov
      22.10.2025 10:23

      Очевидно, что проедал запасы


      1. Tzimie
        22.10.2025 10:23

        Ну большинство моих знакомых айтишников сидят на ипотеке. Какие запасы...


  1. anonymous
    22.10.2025 10:23


  1. Tzimie
    22.10.2025 10:23

    А какой ваш возраст если не секрет? Может просто эйджизм?


  1. kmatveev
    22.10.2025 10:23

    Читабельный текст. Я бы не прошёл эти собеседования, не успел бы сделать за то время, которое ожидается.

    Подозреваю, что задачу на сервис кликов не приняли потому, что хранилище не многопоточно-безопасное, про это ничего не сказано, но для сервисов это должно подразумеваться. Я бы предложил хранилище как Map<Instant, List<Event>>, не стал бы агрегировать на лету по авторам и дням, потому что иметь исходные неагрегированные данные - это хорошо, это типа "хороший вкус" и "здравый смысл", это возможность расширять сервис. При этом в качестве Map использовал бы ConcurrentSkipListMap, а в качестве List использовал бы CopyOnWriteArrayList. Это очень бы упростило вставку. При вызове aggregate() итерировался бы по событиям внутри дня.

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


  1. iv_kingmaker
    22.10.2025 10:23

    В ответ — список типовых задач на leetcode, которые полезно порешать, чем, собственно, и занимаюсь в период перед первым этапом.

    Много раз было написано, что решение "задачек" - не гарантирует, не то что работу, ничего. Достаточно выучить базовые алгоритмы, на которых и строятся все задачи с того же Leetcode, задачи все не выучишь. Шанс, что вам дадут определённую задачу, 1 к 1000 (если не больше, и это только одна площадка, необходимо учитывать, что многие компании немного меняют условия). Списки все вопросов и задач, даются для галочки "видите, компания "заботится" о вас, даже до собеседования".

    Итак, вторая секция. Пришел интервьюер, принес gradle проект в zip-ке. Скинул через чат в зум. Я развернул проект

    Это глупость, откровенно - скачивать непонятные архивы, тем более их разворачивать на компьютере. Учитывая недавние статьи, как таким мошенничеством крадут данные с компьютеров соискателей, откуда вы уверены, что это VK собеседовали? Если хотят проверить ваши знания на проекте, пусть делают, как другие компании - без разворачивания, в онлайн редакторе кода, на github или другим способом.

    Собеседовался к ним однажды в отдел разработки рекламных сервисов, в итоге перевели на отдел разработки аутентификации (VK ID, или как там его). Прошёл собеседование техническое, HR пропала на несколько недель, пока "не пнул" и не написала бы. Узнаю, что прошёл, необходимо пройти ещё собеседование с "директорами". Спрашиваю у неё, собеседование будет носить технический характер или нет. Она ответила - нет, можно не готовиться. В итоге, на созвоне начался допрос, при чём интересного характера - начали спрашивать вопросы за железо (собеседовался на разработчика). В итоге, немного поотвечал, вроде, даже, неплохо и говорят, напишут через несколько дней о решении. HR снова пропала на несколько недель, пока ей не написал. Ответила, что не подхожу. На вопрос, зачем обманули про собеседование - ответила, что она "в афиге" и не ожидала этого потому, что директора ей сказали, что обсуждать будем зарплату и формат работы, "болтать". В итоге, к "этой компании" - отношусь, как к цирку и всем рассказываю (когда уместно). HR забывают про соискателей и не отвечают, в компании врут коллегам, смешно. И так запариваться ради VK, это ужас.

    Я вас понимаю и сейчас в поисках работы сам, при чём достаточно долго (в рамках поиска) и опыт внушительный, сейчас сложно, но и соглашаться на кабальные собеседования - не выход.


  1. hard_sign
    22.10.2025 10:23

    Кадровая служба VK — очень, очень странная. Причём даже нормальный человек, придя туда со стороны, быстро заражается какой-то неведомой бациллой и начинает чудить. Поэтому порадуйтесь, что не попали туда, и удачи в поисках!


  1. anonymous
    22.10.2025 10:23


  1. RoGuS
    22.10.2025 10:23

    Сейчас на рынке часто такая картина... Очень много спецов сидят и ждут когда итшка вновь начнет гореть. С учетом того, что большое кол-во "специалистов" которые прошли курсы все еще сидят на своих местах (хз как), еще какое то время придется подождать, пока их выкинут, и места освободятся.


  1. anonymous
    22.10.2025 10:23


  1. RamTop
    22.10.2025 10:23

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

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

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


  1. anonymous
    22.10.2025 10:23


  1. d3d11
    22.10.2025 10:23

    несколько интеграционных тестов на ручки

    Для тех, кто не в курсе - так в яндексе называют обработчики.