[Перевод] Как победить на собеседовании. Несколько крайне полезных советов для разработчиков
От автора: я разработал и провёл десятки собеседований по программированию. Здесь я расскажу, как меня обыграть
Будем честными, большинство программистов не любят писать код на собеседовании. Некоторые даже угрожают уйти из профессии по этой причине. Но в ближайшее время ничего не изменится. Так что если вы действительно хотите получить работу, то придётся понять, как можно добиться успеха на этих собеседованиях. Я помогу вам. Мы изучим процесс, и я объясню, что именно я хочу добиться от собеседования, так что у вас сложится довольно чёткое представление, как его пройти.
Прежде чем начать, сразу хочу сказать, что если компания мобирается нанять разработчика только и исключительно на основе фрагмента кода, который он написал на собеседовании, то вероятно, вы не захотите работать в такой компании.
Ты больше, чем просто машина для кодинга
Часть 1. Программирование на доске
Кто вообще в этом мире программирует на доске? В самом деле, серьёзно. Тем не менее, я попрошу вас сделать это. Не волнуйтесь, я не сошёл с ума. Я знаю о Google и что доска плохо справляется с автодополнением. Меня это не волнует. Я проверяю не то, насколько красивый код вы пишете на доске, а кое-что другое.
Когда вы получите работу, вам никогда не придётся программировать на доске. Но я гарантирую, что наступит момент, когда мы все будем ломать головы над проблемой перед самым дедлайном, когда мы вымотаны в край, на нас все злятся, а на кону стоит наша работа и репутация. Когда наступит такой момент, мы пойдём в переговорную, столпимся возле доски и будем выяснять, что делать. Быстро.
«Я проверяю не то, насколько красивый код вы пишете на доске»
Хотя мне не нужен программист, который пишет красивый код на доске, но мне нужен тот, кто способен быстро думать на ходу, под давлением, в одной комнате с другими. Проблема в том, что если вы не понимаете, что именно я проверяю, то всё сделаете неправильно. Вы собираетесь доказать, что вы настоящий ниндзя в программировании на доске. Это глупо. Никому не нужен ниндзя в программировании на доске. Вот как меня победить:
1. Вербализуйте свои допущения и постарайтесь их подтвердить
Лучшие разработчики знают, что в фундаментальном смысле каждый баг — это результат неверного допущения. Так что перед тем, как начать писать код, подумайте о необходимых допущениях и спросите меня о них.
2. Думайте вслух
Я хочу получить некоторое представление о вашем мыслительном процессе. Для меня гораздо ценнее ваши размышления о проблеме, чем знание наизусть названия какой-то встроенной функции. Так что думайте вслух. Произносите всё, что приходит в голову.
3. Не бойтесь попросить помощи
Если вы застряли или чего-то не знаете, спросите меня. Вы представить не можете, насколько фантастически дорого компании обходится разработчик, который отказывается просить о помощи, когда где-то застрял. У меня нет времени на программиста, который не даёт результат, потому что делает вид, что у него всё под контролем, а сам бессильно барахтается в одиночестве.
4. Честно покажите свои способности и опыт
Не хочу вас обманывать предыдущим советом. Есть определённый уровень для вопросов и комментариев. Если вы спрашиваете о том, что должно быть очевидно человеку с соответствующими записями в резюме, то это красный флаг. Так что перед началом программирования на доске убедитесь в том, что вы честны со мной в репрезентации своих способностей и опыта.
Часть 2. Программирование на компьютере
В отличие от доски, если я приглашаю вас за компьютер и прошу написать код, то я действительно проверяю, как хорошо вы программируете. Точнее, я проверяю ваше умение соблюдать правила.
Лучше всего понять это, если посмотреть на реальный пример. Один из моих любимых вопросов такой:
Палиндром — это число, буквосочетание, слово или текст, одинаково читающееся в обоих направлениях. Разрешаются корректировки к прописным буквам, пунктуации и пробелам. Некоторые примеры на английском: «A man, a plan, a canal, Panama!», «Amor, Roma», «race car», «stack cats», «step on no pets», «taco cat», «put it up», «Was it a car or a cat I saw?» и «No «x» in Nixon».
Напишите самую эффективную функцию, какую сможете найти, чтобы определить, является ли данная строка палиндромом.
Ваша функция должна принимать строку как параметр и возвращать булево значение (true, если строка является палиндромом, и false, если не является).
Предполагайте, что этот код будет поставлен в реальную систему на рабочем сервере, и пишите соответственно с этим.
Когда я предлагаю такую задачу на собеседовании, первым делом я смотрю, зададите вы мне дополнительные вопросы или нет. Как я уже говорил раньше, лучшие программисты понимают, что допущения — это именно то, что убивает вас в этом бизнесе. Мой совет каждому, кто получил инструкции для написания кода, — сделать паузу и подумать, какие допущения следует сделать для того, чтобы выполнить задание (они всегда есть) и найти способ подтвердить или прояснить эти допущения. Я понимаю, что во время выполнения задачи люди уходят в «тестовый режим» и думают, что им запрещено говорить. Я же полагаю, что вы начнёте с вопроса интервьюеру: «Мне разрешено задать вам один или два вопроса, чтобы прояснить некоторые допущения?» (Я всегда отвечаю «да»), и тогда вы получите ОГРОМНОЕ преимущество.
Хорошие вопросы для этой конкретной задачи:
- Здесь клиентский JavaScript или на стороне сервера?
- В контексте данной задачи может ли считаться пустая строка валидной строкой на входе?
- Нужно ли обрабатывать символы Unicode?
Далее я смотрю, насколько хорошо вы следуете инструкциям. Например, я определил строку как параметр и булево значение как результат. Это то, что выдаёт программа?
Затем я хочу посмотреть, как вы интерпретируете фразу «Предполагайте, что этот код будет поставлен в реальную систему на рабочем сервере, и пишите соответственно с этим». Если вы раньше разрабатывали рабочий софт, то понимаете, что эта фраза означает несколько вещей:
- В коде должны быть комментарии.
- Нужно предусмотреть обработку ошибок или хотя бы ведение логов.
- Программу следует обложить тестами.
- Программа не должна сбоить ни в коем случае.
- Код должен быть легко читаем и говорить сам за себя (легко понятные имена переменных, хорошее форматирование, в идеале — без сложных конструкций и дефектов («lint free»)
Если вы раньше видели код только в учебниках и руководствах, то не знаете, что означают вышеперечисленные вещи. Мой совет: посмотрите на код популярных open source проектов. Особенно тех проектов, которые развиваются уже давно и стабильны. Для JavaScript вполне хорошим примером будет код jQuery на GitHub.
Далее, мне интересно посмотреть, как вы понимаете слово «эффективный» в сочетании с «продакшн системой». Если у вас есть опыт, то вы понимаете, что понятие «эффективный» для программы в продакшне означает три вещи:
- Быстро работает.
- Не занимает память, когда она ей не нужна.
- Стабильна и легко поддерживается.
Вы должны понимать, что пункт № 3 иногда означает некоторый ущерб для пунктов № 1 и № 2.
В этой конкретной задаче я предполагаю, что многие будут применять здесь регулярные выражения. Они универсально подходят для многих языков, быстры и исключительно удобны (правка: регулярные выражения не всегда работают быстро, в том числе с палиндромом, спасибо AlexDenisov в комментариях). Будет вполне обоснованным предположить, что вы знаете основы регулярных выражений, но вы всё равно можете написать код и без них.
Насчёт тестов я хочу увидеть, что вы предусмотрите много тестов, но все они будут проверять действительно разные сценарии. Проверка «mom», «dad» и «racecar» избыточна, это всё один и тот же тест. Я также ожидаю увидеть, что вы включите тесты на прочность (краш-тесты); тесты каких-нибудь строк, которые не являются палиндромами. Рассматривайте пограничные случаи, проверяйте нуль или число. Проверяйте пустую строку или набор специальных символов.
Я задаю эту задачу разработчикам всех уровней, но чем опытнее специалисты, тем более строгие критерии.
Если джуниор выдаёт работоспособное и достаточно простое решение, и всё остальное собеседование проходит нормально, этого достаточно для начала работы и повышения своих навыков.
Для разработчиков среднего уровня хочется видеть какие-то комментарии и хороший стиль программирования. Хочется видеть эффективное решение и, возможно, какой-то тест.
Для ведущих программистов хотелось бы видеть оптимальное решение, чистый и поддерживаемый код, обработку ошибок, комментарии, полный набор тестов. Например, если вы применяете console.log () в JavaScript на стороне клиента, то добавьте комментарий, который даёт понять, что вы знаете о необходимости поддержки логгирования также на стороне сервера.
Вот пример хорошего кода, написанного на JavaScript.
'use strict'; // avoid ambiguity and sloppy errors
/**
* Tests wether or not a given string is a Palindrome
* @param {string} stringToTest - the string to test.
*/
function isPalindrome(stringToTest) {
var start = 0,
end;
// make sure we have a string.
if (typeof stringToTest !== "string") {
// throw if we didn't get a string
throw new TypeError("isPalindrome() expected a string, but got " +
Object.prototype.toString.call(stringToTest) + " instead!");
}
// normalize string by lowercasing and removing non-word characters
stringToTest = stringToTest
.toLowerCase()
.replace(/[^a-z0–9]/ig, '');
if (stringToTest.length === 0) {
// warn if we have no valid characters to test
console.log("No valid characters to test, treated as empty string" +
"\nStack: \n" + new Error().stack);
return true; // an empty string is a palindrome.
}
end = stringToTest.length - 1;
// compare characters from outside in. stop when we get to the middle.
while (start < end) {
if (stringToTest[start] !== stringToTest[end]) {
return false;
} else {
start++;
end--;
}
}
// if we get here, it's a palindrome
return true;
}
// tests (should be in a seperate file using a test framework)
console.log(isPalindrome("something that is not a palindrome") + " = false");
console.log(isPalindrome("something that is \n not a palindrome") + " = false");
console.log(isPalindrome("race \n car") + " = true");
console.log(isPalindrome("") + " = true + warn");
console.log(isPalindrome(" ") + " = true + warn");
console.log(isPalindrome("1221") + " = true");
console.log(isPalindrome("0") + " = true");
console.log(isPalindrome("racecar") + " = true");
console.log(isPalindrome("No 'x' in Nixon!") + " = true");
console.log(isPalindrome("~~!~!~") + " = true + warn");
console.log(isPalindrome("Momsie") + " = false");
console.log(isPalindrome(12)); // blow up
console.log(isPalindrome(undefined)); // blow up
console.log(isPalindrome(null)); // blow up
Очевидно, есть другие способы написать подходящую программу, но это даёт представление, о чём я говорю.
Если я даю задание на дом, то ожидания ещё выше.
Часть 3. Алгоритмы
Некоторые интервьюеры будут просить написать реализацию конкретного алгоритма. Лично я считаю это гигантской потерей времени. Гораздо более важно для меня, чтобы вы понимали, какой алгоритм применить для какой задачи. Реализацию всегда можно найти в Google.
Тем не менее, поскольку интервьюеры попросят это, лучше освежить знания в памяти перед собеседованием. На Khan Academy есть отличный бесплатный курс.
Часть 4. Не сдаваться без борьбы
Если вы не способны решить предложенную задачу, всегда есть некоторые вещи, которые можно сделать, чтобы сохранить шансы получить должность.
1. Не сдавайтесь слишком легко
Убедитесь, что я заметил ваши усилия. Если вы из тех, кто сдаётся, когда становится трудно, я не будут тратить на вас время.
2. Псевдокод
Когда проблема возникла из-за того, что вы не можете вспомнить точное название функции или другое синтаксическое правило, используйте комментарии для объяснения, что вы хотите сделать, в псевдокоде. Если у меня возникнет ощущение, что вам достаточно одного запроса в Google, чтобы решить задачу, это не повлияет на положительный результат. Особенно если вы отлично показали себя на остальном собеседовании.
3. Назовите известные неизвестные
Если вы застряли полностью, то остаётся последний вариант: назовите мне всё, что вам нужно знать для решения задачи, и скажите, как в реальном мире вы получите эту информацию. Расскажите максимально подробно. Если вы говорите, что вам понадобится помощь, то скажите, к кому конкретно обратитесь (должность) и что конкретно спросите (максимально конкретный вопрос, если возможно). Если вы говорите, что поищете в интернете, то назовите конкретные поисковые запросы, по которым будете искать. В этом сценарии вам требуется убедить меня, что вы действительно можете решить проблему в реальных условиях, если будете работать на меня.
Часть 5. Практика, практика, практика
Пожалуй, самое важное для успешного собеседования по программированию — хорошая подготовка. Лучше всего практиковаться со стандартными вопросами снова и снова, пока вы не выучите их назубок. Если много тренироваться, то вы сможете отвечать на вопросы, которые не встречали ранее. У вас появится уверенность и вы сможете связать любой вопрос с чем-то другим, что встречали раньше.
Я составил большой список онлайн-ресурсов с примерами вопросов и советами по программированию для 50+ различных языков программирования и технологий, включая C#, JavaScript, Mongo, Node и так далее…
Список здесь (подписка на рассылку) и ниже в pdf.