Технически — берём. Почему после хорошего интервью мы всё же отказали кандидату

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

Код можно переписать. Систему — пусть и постепенно — перестроить. А последствия неудачного найма команда иногда разбирает месяцами.

Я провожу технические интервью и участвую в оценке senior-кандидатов. Раньше для меня главный вопрос был довольно прямым: достаточно ли человек силён технически?

Сейчас этого уже недостаточно.

Окончательно я это понял после одного интервью.

Интервью, после которого не хотелось отказывать

Кандидат шёл на серьёзную позицию.

Резюме выглядело хорошо: Java, Spring, базы данных, Kafka, распределённые системы. На интервью он тоже производил хорошее впечатление. Говорил спокойно, без попыток впечатлить количеством терминов. Если чего-то не знал точно, не начинал выкручиваться.

На System Design тоже всё было нормально.

Уточнял требования. Спорил про компромиссы. Не пытался любую систему автоматически собрать из микросервисов, Redis и Kafka.

Когда мы обсуждали консистентность, было видно, что человек понимает разницу между учебным ответом и реальной системой: где действительно нужна строгая консистентность, где можно жить с eventual consistency, а где добавление очереди просто переносит проблему в другое место.

После встречи у меня не было причины ставить минус.

Более того, я уже примерно представлял, куда его можно поставить в команде и с какого участка ему будет проще начать.

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

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

Не на интервью и не от самого кандидата.

Со стороны.

Я специально не буду писать, откуда именно. Это не была какая-то база, в которой написана «истина о кандидате». Просто ещё один источник информации, причём источник, который вполне мог ошибаться.

Игнорировать его тоже не хотелось.

Мы сели втроём: я, hiring manager и человек, который вёл процесс найма. Попытались отделить конкретные факты от чужих интерпретаций.

Фразы вроде «с ним было невозможно работать» сами по себе ничего не значат. У двух людей после одного конфликта могут быть совершенно разные версии событий.

Но там были и вполне конкретные утверждения, которые можно было проверить.

Поэтому мы вернулись к кандидату и дали ему возможность объяснить ситуацию.

Без ловушек. Без попытки поймать на слове.

Примерно в формате: появилась такая информация, хотим понять, что произошло с вашей точки зрения.

Разговор получился довольно неприятным.

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

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

Часть фактов подтвердилась.

И это были не вещи уровня «сложный характер» или «не сошлись с менеджером». Речь шла о профессиональной надёжности.

После этого решение изменилось.

Кандидата мы не наняли.

Подробности я сознательно не раскрываю. Они здесь и не особенно важны.

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

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

После этого случая я перестал воспринимать хороший System Design как достаточное основание для hire.

Что вообще можно проверять, а куда лучше не лезть

Здесь есть неприятная граница.

Дополнительная проверка кандидата очень быстро может превратиться в сбор компромата. Мне такой подход не нравится.

Техлид не должен играть в детектива. Компания тем более не должна делать вывод о человеке на основании одного чужого отзыва.

Личная жизнь кандидата меня вообще не интересует.

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

И даже наличие такого сигнала ещё ничего не доказывает.

Это только повод задать дополнительные вопросы.

В том случае мы сначала сделали очень простую вещь: выписали отдельно конкретные утверждения.

«Токсичный» — не утверждение.

«Постоянно конфликтовал» — тоже почти бесполезная информация.

А вот если есть конкретный проект, конкретная роль и конкретное действие, это уже можно проверять.

Одного источника всё равно мало.

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

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

Следующий шаг — разговор с самим кандидатом.

Я обычно стараюсь начинать его без обвинительной формулировки:

есть информация о такой ситуации, расскажите, пожалуйста, как вы её помните.

Мне неинтересно наблюдать, как человек нервничает. Нервничать на таком разговоре нормально.

Интереснее другое: насколько история остаётся конкретной, когда начинаются уточняющие вопросы.

Какую именно роль человек играл?

Что было его решением?

Какие варианты были?

Что произошло после?

Что он сделал сам?

Что сегодня сделал бы по-другому?

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

Смотреть имеет смысл только на общую картину.

То же самое касается резюме.

Фраза «проектировал высоконагруженную платформу» может означать очень разные вещи.

Один кандидат действительно принимал ключевые архитектурные решения.

Другой был хорошим разработчиком в команде, где архитектуру проектировал кто-то ещё.

Оба формально могут написать в CV похожую строку.

Разница становится видна только в деталях.

Какие варианты рассматривали? Что выбрали? Почему? За какую часть отвечали именно вы? Какое решение оказалось неудачным?

Рекомендации я воспринимаю примерно так же — как дополнительную точку зрения.

Они бесполезны, если нужны только для того, чтобы подтвердить решение, которое уже принято.

Почему Java-викторина всё хуже работает для senior

Классическое техническое интервью очень удобно.

Можно пройтись по HashMap, happens-before, синхронизации, GC, Kafka consumer group, уровням изоляции PostgreSQL.

Через полтора часа получается аккуратная таблица: здесь хорошо, здесь средне, здесь пробел.

Проблема в том, что сама ситуация довольно искусственная.

Кандидат знает формат интервью и готовится к нему. Это нормально. Мы все готовимся к важным встречам.

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

Вопросы с известными правильными ответами плохо показывают границу реального опыта.

Можно очень точно рассказать, как работает GC, но ни разу не выбирать его настройки для живой системы.

Можно прекрасно объяснить delivery semantics в Kafka, но никогда не разбираться с повторной обработкой сообщений после реального сбоя.

Теория здесь вообще ни при чём. Хорошая теория нужна.

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

Сейчас эта граница ещё сильнее размывается.

Есть курсы, огромные базы вопросов, AI. Я сам использую AI в работе и не вижу здесь проблемы.

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

Поэтому после стандартного ответа про Kafka я часто спрашиваю что-нибудь вроде:

А где вы сами на Kafka ошиблись?

Что сломалось?

Почему первое решение выглядело нормальным?

Как вы поняли, что проблема именно там?

Что пришлось менять?

Такие разговоры обычно быстро отличаются от заученного ответа.

У реальной истории почти всегда есть неидеальные детали.

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

Человек помнит эти вещи именно потому, что прожил их.

Один из моих любимых вопросов:

«Расскажите о техническом решении, которое вы поддерживали, а потом поняли, что оно было ошибочным».

От senior-инженера я точно не жду карьеры без ошибок.

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

Хороший ответ обычно довольно прозаичный.

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

И это звучит гораздо убедительнее идеальной истории успеха.

Иногда ответ идёт совсем в другую сторону: архитектор ошибся, аналитики плохо описали требования, DevOps неправильно настроили инфраструктуру, QA пропустил баг, менеджер неправильно спланировал релиз.

Такое действительно бывает.

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

Не потому, что это автоматически плохой кандидат.

Просто это интереснее очередного вопроса про ConcurrentHashMap.

Техническая сила и профессиональная надёжность — не одно и то же

В инженерной команде удивительно много вещей держится на доверии.

Мы просто редко формулируем это как отдельное требование.

Мы не ставим второго senior-разработчика перепроверять каждое действие первого.

Если коллега говорит, что проблема не в его сервисе, команда некоторое время опирается на эту информацию.

Если senior говорит, что изменение API обратно совместимо, другие команды строят работу исходя из этого.

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

Без этого невозможно нормально работать.

Когда доверие исчезает, появляется постоянный дополнительный контроль.

Люди начинают перепроверять сообщения, решения и обещания. На обычные задачи уходит больше времени. Разговоры становятся длиннее.

Причём технически такой человек вполне может быть очень сильным.

Для меня это важное различие.

Надёжность — это не удобство.

Мне не нужен senior, который со всеми соглашается.

Наоборот, хорошие специалисты регулярно спорят. Иногда довольно жёстко. Задают неприятные вопросы. Останавливают инициативу, в которую уже вложили несколько недель, если видят серьёзную проблему.

Это нормально.

Совсем другая ситуация — когда человек начинает искажать факты, скрывать важные детали или регулярно переносить свою ответственность на остальных.

Если смешать эти вещи, можно довольно быстро прийти к найму только максимально бесконфликтных людей.

Я не думаю, что это хорошая команда.

Слабого разработчика при этом часто обнаружить проще.

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

С технически сильным специалистом всё сложнее.

Он может действительно закрывать самые тяжёлые задачи.

И поэтому каждой новой проблеме легко находится объяснение:

ну да, зато релиз он тогда вытащил.

Или:

да, с ним непросто, но только он понимает этот модуль.

Проходит год.

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

Я видел похожие ситуации в разных командах.

«Он очень сильный» — хороший аргумент в пользу человека.

Но не универсальный.

Что я изменил в интервью

Java, базы данных и архитектуру я по-прежнему проверяю.

Без этого техническое интервью теряет смысл.

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

Есть несколько вопросов, которые для меня хорошо работают:

— Расскажите про самый тяжёлый production-инцидент за последний год. Что лично делали вы?

— Какое ваше техническое решение пришлось потом переделывать?

— Когда вы в последний раз были серьёзно не согласны с техлидом или архитектором? Чем закончился спор?

— Был ли случай, когда менее опытный коллега оказался прав, а вы — нет?

— Какое решение в вашем текущем проекте вы считаете плохим и почему команда всё ещё с ним живёт?

— Расскажите про задачу, срок которой вы сорвали. Что произошло и что вы сделали после?

Я никогда не задаю весь список подряд.

Обычно беру два-три вопроса и дальше иду за историей кандидата.

Если человек рассказывает про production-проблему, спрашиваю про нагрузку, мониторинг, гипотезы, альтернативы, последовательность действий.

Если говорит про архитектурное решение — интересно понять ограничения и почему выбрали именно этот вариант.

Если обсуждаем конфликт — важно не то, кто там оказался «прав».

Гораздо интереснее, как вообще принималось решение и что человек сделал после него.

Мне не нужны идеально сформулированные ответы.

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

Это нормально.

Мне нужна связная картина происходившего и понятная зона личной ответственности.

Если появляется какой-то внешний сигнал, вопросы становятся более адресными.

Есть сомнения в архитектурном опыте — подробно разбираем систему, которую кандидат называет своей.

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

Есть вопросы к работе в команде — разбираем реальный конфликт, а не просим назвать три сильных стороны и две слабых.

Конечно, и такой подход ничего не гарантирует.

Можно провести отличные интервью и всё равно ошибиться с наймом.

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

У найма вообще нет способа получить стопроцентную уверенность заранее.

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

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

После той истории

Я иногда вспоминаю того кандидата.

И я правда не знаю, как он работал бы у нас.

Возможно, никаких проблем вообще не возникло бы.

Возможно, тот случай из его прошлого был исключением.

Этого уже невозможно проверить.

Но после того интервью у меня появился дополнительный вопрос, который я иногда мысленно задаю в конце разговора с senior-кандидатом:

если в три часа ночи упадёт production и мы вдвоём будем пытаться понять, что произошло — насколько я смогу опираться на то, что этот человек мне говорит?

Ответ на этот вопрос редко появляется после обсуждения HashMap или Kafka.

Обычно он начинает складываться, когда человек рассказывает про реальные проекты.

Особенно про те моменты, где всё получилось не так аккуратно, как хотелось.

33
11