Собеседую программистов на Java. Единый набор вопросов для любого уровня
В своей карьере мне приходилось быть и разработчиком, и менеджером, и даже один раз «CTO» в небольшом стартапе. И, разумеется, приходилось проводить большое количество собеседований кадидатов. Поэтому для себя я выработал такие правила проведения технических собеседований:
- всем кандидатам задавать одинаковые вопросы,
- вопросы должны быть такие, чтобы на них ответил и junior, и senior, но по разному,
- после трёх вопросов должен быть понятен уровень кандидата.
И вот такие три вопроса для Java-разработчиков у меня получились.
Расскажите про HashMap
Да-да, тот самый стандартный вопрос, с которого начинается 50% собеседований. Почему я его задаю? Потому что на него можно ответить очень и очень по разному.
- Идеальный ответ начинается с постановки задачи. Зачем нам нужна такая структура? Какую именно задачу она решает? Как выглядит тривиальное решение данной задачи «в лоб» и чем оно плохо?
- «Бонусные очки» за исторический экскурс, знание автора решения, хотя бы примерный год его появления (не в Java, разумеется)
- Ответ хотя бы junior’а обязан включать способы использования структуры. Какие методы она поддерживает.
- От middle-разработчика требуется понимание внутреннего устройства, а также описание контрактов функций hashCode () и equals (), функциональных требований к ним
- «Бонусные очки» за описание нефункциональных требований к hashCode () и equals ()
- «Бонусные очки» за рассмотрение вопроса использования HashMap в многопоточной среде.
- «Бонусные очки» за рассмотрение альтернатив HashMap — их перечисление, сравнение по сложности реализации, использования, скорости работы в общем, идеальном и самом плохом случаях.
- «Бонусные очки» за альтернативы HashMap в виде отдельных компонентов системы (например, баз данных и «внешних» кэшей).
- «Бонусные очки» за описание того, как HashMap используется в базах данных, и почему обычно используют индексы на основе двоичных деревьев, а не HASH-индексы.
Как видите, очень большое количество «бонусных опций», о которых можно поговорить с senior’ом. А о скольких пунктах вы сами можете поговорить хотя бы минут 10?
Если будет скучно, замените HashMap на TreeMap.
Напишите SQL…
Ага, и снова «стандартный» вопрос, который 10 лет назад был на каждом собеседовании. Сейчас уже реже, видимо из-за моды на nosql. Но умение работать с данными всегда нужно, и программисты, понимающие декартово произведение, всегда полезнее (и дороже) тех, кто ограничивается общим пересказом учебника.
А вопрос звучит так:
Пусть в базе данных существуют две таблицы: students и groups. У каждого студента указан идентификатор группы group_id, к которой он относится. Напишите SQL-запрос без использования вложенных, выводящий список групп (или количество групп) без единого студента
Правильный ответ будет, разумеется, содержать не просто JOIN, но LEFT JOIN со сравнением значения на NULL. Самое интересное будет поговорить с кандидатом о том, какие ошибки можно допустить при написании запроса, и почему именно запрос не будет работать, если их допустить. Почему нельзя сравнивать с NULL через равенство? Почему не будет работать простой JOIN?
Бонус за индексы, которые ускорят работу этого запроса и за рассмотрение вариантов SQL в разных диалектах (разных СУБД).
Найдите ошибки в коде
Кандидату озвучивается задача так:
Предположим, что вам на code review приходит Pull Request (Merge Request) от другого разработчика. В этом request’е большое количество разных файлов, но один из них выглядит следующим образом (приведён код класса целиком):package ru.mycompany.utils; /** Wrap around Lock to simplify interface */ class LockWrapper { private Lock lock; public wait() { this.lock.wait() } }
Будут ли у вас замечания к этому коду, и если будут, то какие? Пропустите ли вы запрос с таким файлом далее (в master-ветку), или же потребуете переделать, и почему?
Разумеется, и здесь есть как минимум три уровня.
- Любой junior должен указать на синтаксические ошибки, которые есть в этом коде. Разработчик должен указать, почему код не скомпилируется. И проблема не только в синтаксисе, разумеется.
- Разработчик должен знать, почему даже если код скомпилируется, он не заработает. И как необходимо этот код поправить, чтобы он заработал. Разработчик должен уметь использовать и конструкцию synchronize, и классы из пакета java.util.concurrent, и знать, почему одно второму не третье.
- Идеальный разработчик же должен начать с вопроса, а зачем этот код нужен, какую задачу он решает, и может ли он её решить, даже если исправить все существующие проблемы в этом коде.
В процессе ответа вместе с кандидатом приводим код к «идеальному» виду. Итоговый вид, разумеется, зависит от квалификации кандидата. Лучший из моих кандидатов нашёл здесь 13 ошибок. Не считая «самой главной ошибки».
Бонусом можно поговорить о том, какие средства автоматического контроля кода следует использовать, чтобы найти хотя бы часть присутствующих ошибок.
Вместо заключения.
Один совет, который хочется дать всем тем, кому придётся собеседовать будущих коллег. Не пытайтесь дать ответ — подходит человек или нет. Формулируйте своё мнение либо в виде грейда (если у вас в компании они приняты), либо в виде денежной суммы, которую вы готовы заплатить кандидату, чтобы он работал в вашей компании. Это, во-первых, упрощает принятие решение вам, ведь оно не будет чёрным или белым, во-вторых — тому, кто будет принимать финальное решение или сравнивать итоги нескольких собеседований.