Хотели как в FAANG, а вышло как всегда или Опыт собеседования в Тинькофф в 3 актах

в 8:47, , рубрики: java, Карьера в IT-индустрии, собеседование

Предисловие

Около года назад я задался целью получить оффер от FAANG. Как следствие, постоянной частью моей жизни стали тематические форумы, площадки и вся сопутствующая атрибутика. Спустя какое-то время я попробовал себя на собеседованиях в околоFAANGoвые компании: Lyft, Spotify, Booking и т. д, где-то успешно, где-то не очень. В это же время мне порекомендовали попробовать пройти собеседование в Тинькофф банк, который внедрил схожий процесс.

После стандартного общения с HR менеджером была получена ссылка на описание процесса собеседования. “Хм, почти что FAANG + тех. интервью по Primary Skill”, - подумал я и сказал, что готов приступать. В тот же час было назначено 2 интервью: техническое и coding, а вот 3 этап, system design, нужно было заслужить успешным прохождением первых двух. Почему именно эти 2 части являлись основополагающими, осталось неясным.

Акт первый, технический

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

  • Ревью кода. Разнообразные задачи от Spring до concurrency.

  • Spring до concurrency. Вопросы по Spring оказались весьма тривиальными, входящими в подборку “ТОП-25 вопросов по Spring” (скоупы бинов, виды прокси и т. д.). Можно ли такими вопросами действительно проверить понимание и опыт использования Spring? Сомнительно.

  • Транзакции. ACID. Уровни изоляций. Как устроена работа в Spring? Несомненно, данный топик поражает своей новизной. Почему бы не отойти от заученной статьи с Википедии (которая читается 5 минут) и стандартных вопросов как будто бы про транзакцию (а на самом деле про прокси в Спринге), не мучить Senior+ кандидата выученными статьями, а поговорить о необходимости транзакций, архитектурных подходах и сопутствующих темах? Тем более вы рекомендуете к прочтению книгу “Высоконагруженные приложения. Программирование, масштабирование, поддержка / Мартин Клеппман”, где тема БД, транзакций и прочего раскрыта очень хорошо.

  • Concurrency. И снова стандартные вопросы про “deadlock, synchronized, reentrantLock”, принцип “happens before” и “volatile” (хотя это JMM, знатоки, не кидайтесь тапками), как-то по верхам цепляем java.util.concurrent. Зачем-то пересказываем друг другу то, что миллион раз слышали, а на практике почти никогда не применяли. В голове крутится “зачем, почему, ведь мы можем обсудить столько всего”. “Столько всего” - это:

    • Базовая теория потоков (какими потоками оперирует Java, почему, есть ли альтернативы в Java или других JVM-based языках, их плюсы и минусы).

    • Методы поиска deadlock и livelock с различными UI тулами или без них (только терминал, только хардкор). Для кандидатов уровня ниже можно просто дать на ревью thread dump.

    • Если уж дошли до java.util.concurrent, то вместо вопроса, что за зверь ConcurrentHashMap, давайте посмотрим на изменение подхода к ее реализации в разных версиях JVM и поразмышляем о причинах. Также можно обсудить “диковинные” коллекции в виде зоопарка очередей и, к примеру, skip lists (заодно проверив теорию алгоритмов).

    • Думаю, для “бесплатного” списка тем достаточно)

  • JMM и т. д. Вот тут прозвучал вопрос, на котором я, признаюсь завис. “Что знаешь о JMM?” Максимально высокоуровневый вопрос, на который мозг начинает генерировать: “Что от меня хотят услышать? Стандартное определение правил из спецификации типа happens before, reordering? А может, типы мониторов, их схему переходов, цикл парковки потоков? А может, еще глубже о работе с ОС?” В общем, не смог я вспомнить, с чего начинаются статьи “JMM, топ 10 вопросов”. “Кое-что знаю, но гораздо меньше, чем Шипилев” - отшучиваюсь и решаю брать инициативу в свои руки. Быстро выдаю всё, что помню про hb, и рассказываю о том, какие проблемы решал за последние несколько лет, тем самым решив перескочить на тему Java Memory. Сразу оговариваюсь, что про heap говорить не будем, так как здесь всё уже сказано и описано, а обсудим лучше NonHeap. Рассказываю о том, почему Spring Boot application не сможет долго жить на 256 Mб оперативы и при чем здесь non-heap (на самом деле, очень советую добавить вопросы про это в интервью, так как приложений, запускающихся не в контейнерах, почти не осталось). Плавно перехожу на коварную Cassandra (как пример сервиса на Java) и ее работу с offheap, заканчиваю тем, что в великолепном докладе Андрея Паньгина всё есть и он мне очень помог. Складывается впечатление, что такого мой собеседующий не ожидал. Возникает неловкая пауза, которую я решаю прервать вопросом “Обсудим gc? Недавно подбирал оптимальные настройки для нашей конфигурации Кассандры, могу рассказать”. То ли из-за ограничений по времени, то ли не выдержав пытку Кассандрой, собеседующий завершает данный блок.

  • Вопрос со звездочкой. Так как перед собеседованием я прочитал подборки “Топ-50 вопросов по Java, Spring и т. д”, получаю вопрос повышенной сложности со следующими входными данными: Есть сервис, работающий с Third-party сервисом. Также данный сервис работает с реляционной базой, в частности Postgres. В какой-то момент сервис начинает тормозить. Каков алгоритм моих действий? Последовательность моих рассуждений:

    • Полагаю, что в моем распоряжение есть все необходимые метрики системы и окружения. Поэтому первым делом предлагаю проверить наличие пиков в графиках latency: запрос в БД, запросы к third-party сервисам, сетевые задержки. Если проблема в БД - то смотрим на количество локов и потребление CPU (потребление memory нам ничего не даст, так как в БД встроен механизм кэширования). Есть проблемы - тюним БД или оптимизируем запросы.

    • Интервьюер отвечает, что с латенси все в порядке, поэтому я предлагаю проверить метрики JVM, в том числе GC (могли увеличиться паузы на stop-the-world).

    • Переходим к вопросам о том, что же делать, если проблема в медленных ответах third-party системы. Предлагаю следующий алгоритм решения:

      • Письмо ответственным за систему с подробным описанием проблемы

      • Ограничение кол-ва запросов к данной системе с помощью rate-limiter (предлагаю отправить письмо с данной просьбой, пока поведение системы не будет исправлено). Предполагаю, что на нашей стороне будет реализована корректная обработка отклоненных запросов.

      • Использование сircuit-breaker на нашей стороне, дабы ограничить кол-во запросов к данной системе.

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

Акт второй, coding

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

  • Не используйте для созвона телефон: Вы будете много кодить в онлайн-IDE, рисовать схемы и общаться с интервьюером.

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

Из этого я сделал вывод, что решать задачи потребуется в онлайн-IDE вроде Coderpad, а по сложности они будут ближе к easy (возможно, middle) на leetcode. Но, как говорится, мои ожидания - это мои ожидания.

В начале собеседования интервьюер сообщил, что меня ждут 2 задачи, и время я должен рассчитывать сам.

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

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

Вторая задача оказалась уровнем выше. Я сразу определил, что решаться она должна методом DP, и тем самым словил диссонанс с ожиданиями: “облегчённые задачи по кодированию, нацеленные на умение использовать простые структуры данных”. Не считаю, что DP задачи, требующие двумерного массива (в простом для понимания решении), можно назвать “облегчёнными”. Объяснив, как в принципе решаются такие задачи, я взял несколько минут на раздумье, но не смог составить рекуррентную формулу, честно об этом сказав. Затем мы вывели формулу вместе с интервьюером - на этом этапе я откровенно не блистал. После этого интервьюер сообщил мне, что данный этап собеседования завершен, и мы попрощались. (Сделанные выводы: стоит подтянуть задачи на DP.)

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

Акт третий, мой любимый. System design

Приглашение на System design секцию стало для меня сюрпризом, поэтому я допустил две ошибки: выбрал не совсем удачное для себя время интервью и не уточнил, какой редактор для проектирования будет использоваться (казалось, что на первой встрече был упомянут Google Draw). 

На интервью было предложено спроектировать Messenger (стандартный дизайн для FAANG собеседований). Решать задачу я собирался по удобной для себя схеме:

  1. Сбор требований

  2. Расчет ресурсов

  3. HLD (High Level Design)

  4. Обсуждение технологий

  5. Возможно, обсуждение API, схемы БД

  6. Обсуждение недостатков и компромиссов

Первые 2 пункта мы проскочили достаточно быстро. Я как мог боролся с неведомым  прежде SketchTool и рисовал HLD. Сразу оговорил, что в мессенджерах используется WebSocket протокол, и объяснил, почему. При отправке сообщения оно должно было попадать в очередь, я предложил Kafka (предупредив, что мы будем относится с осторожностью к созданию большого количества топиков из-за ограничений на файловые дескрипторы). Оттуда сообщение направляется в Cassandra и, при необходимости, на Message Server. 

В какой-то момент мы с собеседующим, казалось, полностью перестали понимать друг друга. Он настойчиво требовал изобразить на схеме, уже полной компонентов, flow с потоками данных (что для меня в скетчбуке оказалось просто невыполнимой задачей). По API я обратил внимание, что сообщения мы пересылаем по websocket, и роутиться запросы будут на основе посылаемого Payload, однако мы продолжили описывать API. По схеме данных я заострял внимание на partitionKey и  важность их выбора, однако собеседующий не понимал, почему работать с большим партишеном плохо, и вообще закрадывалось подозрение, что он не хотел видеть в данном System Design BASE-системы, хотя расчеты говорили о другом.  

Со своей стороны могу сказать, что прохождение данного этапа было далеко от идеала, ввиду путаницы по подключениям и генерации messageId, себя я бы оценил на 6 из 10.В конце собеседования я получил фидбэк, что мой System Design плох по perfomance и latency, так как содержит очень много компонентов и медленных сервисов вроде Kafka. Занавес. “Надо было рисовать 3 квадратика”, - подумал я, - “один клиент, другой - чат-сервис монолит, третий - vendor-specific db, вроде Oracle”.

Уже после этого интервью мне понадобилось зайти в чат приложения Тинькофф, и он сразу напомнил мне о заключительном этапе. Почему? Потому что чат постоянно терял связь с сервером по причине его недоступности. Здесь я понял, что был прав и от меня действительно требовался монолит в 3-х квадратах… 

Заключение

Так почему же получилось “как всегда”? Конкретно на этапах, характерных для FAANGa, я выделил для себя несколько причин:

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

  • Ни на одном этапе не был соблюден тайминг. Все этапы длились на 10-15 минут больше запланированного. (хотя на встрече с hr, было предложено ставить этапы друг за другом, но для себя я просил получасовой перерыв) 

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

  • Не было знакомства с инструментами, которые использовались во время интервью

Хочется верить, что описание моих впечатлений окажется полезным и, возможно, поможет что-то улучшить. Мои предложения:

  • Заранее определиться с редактором для кодинга (если это будет online редактор, то высылать кандидату ссылку заранее, чтобы он мог поработать с редактором и настроить его под себя).

  • Не давать субъективных оценок уровню алгоритмических задач - слово “облегченные” может восприниматься разными кандидатами очень по-разному.  

  • Предупреждать о том, какой именно редактор будет использоваться для System design, чтобы кандидат мог потренироваться. Все редакторы очень разные, и на своем опыте могу сказать, что привыкнув к популярным googleDraw и excilaryDraw, мгновенно переключиться на Sketch Tool было весьма тяжело. 

  • Если вы стремитесь к распределенной архитектуре (судя по рекомендации книги “Высоконагруженные приложения. Программирование, масштабирование, поддержка / Мартин Клеппман”, это именно так), то стоит придерживаться её принципов и на System Design секции. Кроме того, в рекомендации можно добавить ссылку на книгу System Design Interview – An insider's guide (часто идёт в паре с рекомендованной вами). 

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

  • Если процесс интервью и вопросы являются тайной, то ввести NDA для собеседующихся.

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

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

Автор:
arkashaErema

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js