Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Привет, Хабр! Меня зовут Леонид Титов, я бэкенд разработчик в #CloudMTS. Так уж сложилось, что я не только пишу код, но и иногда собеседую кандидатов. Мне нравится процесс, и, думаю, у меня это получается.
Начал я этим заниматься ещё на предыдущем месте работы, где мы с тимлидом собирали новую команду. С тех пор прошло уже N лет, практика продолжилась, и после очередного собеседования я решил упорядочить свои знания. Кто-то считает, что от собеседований вообще толку нет, а кто-то наоборот (не будем показывать пальцем) проводит их в 3-5 раундов. Я уверен, что собеседования нужны, но важно четко понимать, зачем именно.
На всякий случай уточню: в статье речь пойдет не столько про конкретные вопросы (хотя они тоже будут), сколько про выработанную мной методику и принципы, которыми я руководствуюсь, задавая те или иные вопросы.
Еще я поделюсь неожиданными впечатлениями от ситуации, когда оказался «по ту сторону», лайфхаками, фейлами и неплохо зарекомендовавшими себя практиками. Про soft skills тут ничего не будет — это отдельная важная тема. Прежде всего мы затронем вопрос профпригодности, определения ее наличия или отсутствия. Во второй половине статьи приведу собственный список вопросов, переведенный на русский, с комментариями.
Ниже мы обязательно затронем эту тему подробнее, а сейчас предлагаю зафиксировать тезис. Я считаю, что техническое собеседование призвано дать понимание, достаточно ли профпригоден кандидат, чтобы приступить к работе завтра. Да или нет.
Здесь стоит уточнить, какие ошибки собеседующий разработчик может с большой долей вероятности совершить.
Поясню, что я имею в виду. Допустим, мы собеседуем кандидата в разработчики на языке Х и видим, что он его отлично знает. У меня есть огромнейший бэкграунд работы с конечными автоматами (машинами состояний) — знаю о них больше, чем написано в университетском курсе. Я могу спросить кандидата: стоит ли выражать состояния целым числом, числом с плавающей точкой или строкой, какие плюсы и минусы есть? Мы сломали много копий на этом, и для меня ответ очевиден.
Нужно ли спрашивать об этом кандидата? Нет. Потому что это никакого отношения к профпригодности не имеет. Даже если нам с этим работать. Зато есть шанс, что кандидат на предыдущей работе был в команде, где это было «в эфире», слов нахватался, на вопрос ответит, хотя на самом деле как специалист слабенький. Welcome false positive.
Приведу еще один вариант «плохого» вопроса. Например, мы собеседуем разработчика на Go и просим его рассказать, как сделать семафор с помощью канала. Почему этот вопрос плохой?
Как понять, кто вам нужен? Заранее составьте список того, что точно должен знать кандидат как свои пять пальцев. И если он этих вещей не знает — вы его брать точно не будете.
Например, если мы берем разработчика на Go и его знания каналов или слайсов находятся на уровне «прочитал два раза, один раз попробовал», вряд ли он нам подойдет. Наверное, такие вещи он должен знать так, чтобы с ходу ответить на любой заковыристый вопрос, даже если его разбудить среди ночи.
А что делать, если мы работаем с брокером сообщений Х, а кандидат про него ничего не знает? Повод ли это его не брать или даже просто поставить минус? Уверен, что нет.
Как я уже говорил выше про такие вопросы:
А вот по тем вопросам, которые мы определили как «профпригодность», знание должно быть 100% и абсолютное. Каждая команда сама должна определить, что это будет за перечень.
Окей. А если потенциальный соискатель прочитает эту статью, вопросы, подготовится и обманет собеседование. Возможно ли такое?
Опасаться не стоит. Есть железобетонная методика выявления того, насколько человек глубоко знает предмет. Называется она Asymmetric Information Management technique или просто AIM technique — техника ассиметричного управления информацией.
Если коротко, принцип достаточно простой: когда люди рассказывают о том, что действительно было, и/или разбираются в предмете, им нравится погружаться в детали. И наоборот — избегают погружения, когда знакомы с темой поверхностно или рассказывают небылицы. Техника с успехом применяется правоохранительными органами, и некоторые говорят, что работает она лучше полиграфа.
Однажды мы собеседовали кандидата на роль разработчика Go и позволили одному из коллег попробовать себя в роли интервьюера, я же просто слушал. Он задавал достаточно тривиальные вопросы «по списку» — например, про слайсы в Go — а кандидат уверенно отвечал. На фоне было слышно, как он гуглит. Минут через 7 я решил вмешаться и на тривиальных вещах про слайсы просто стал копать в детали. На втором вопросе кандидат просто повесил трубку. Мы даже сначала подумали, что это обрыв связи, так все неожиданно произошло. Но нет. Он видимо, что-то понял :)
Так что копайте вглубь, в детали, и обман не пройдет.
Я очень долго никуда не собеседовался. Хотя «долго» — понятие относительное. 15+ лет, это долго? Естественно, пропадает навык. Вообще это парадокс — только ты выработал навык находить работу, нашел ее, и он становится больше не нужен. А пока работу не ищешь, скилл атрофируется.
Почему я не искал работу? Потому что переходил из одного удивительного проекта в другой, было не до этого. Плюс мой технологический стек отличался от того, который был востребован на рынке.
Почему я стал искать работу в ±2019 году? Во-первых, ни один из моих стартапов не принес мне миллиарда. Начали подходить к завершению обязательства по одному интересному, но малобюджетному проекту, а зарабатывать больше хотелось (к тому же я женился). Во-вторых, к моему немалому удивлению неожиданно обнаружилось, что каким-то совершенно непостижимым образом одна «никому не нужная» технология из моего стека является неожиданно очень даже нужной. Java куда-то начала сдавать, а крупные компании «полюбили» Go, который я полным ходом использовал для промышленных проектов. И я решил попробовать — почему бы и нет?
Первое же собеседование поставило меня в тупик. Мне было совершенно непонятно, зачем мне задавать вот эти все вопросы, если можно посмотреть на фото работающих продуктов? Зачем спрашивать, как устроен слайс в Go, если человек пришел ногами и принес стопку фот того, что работает в проде? Было непонятно.
И вот спустя месяц меня просят присоединиться к собеседованию кандидата на Go. Для подстраховки, ну… или не знаю зачем. Я принял инициативу, и коллеги потом сказали, что «это было круто, уровень как в одной-большой-компании» (это был приятный комплимент, хотя я, честно говоря, не знаю, как там у этой компании). С тех пор я стал проводить их всегда.
Я почти сразу получил ответ, зачем задавать тривиальные вопросы. Очень просто. Примерно 9 из 10 кандидатов не знали языка. Они прочитали о нем в интернете, но что-то конкретное сделать не могли. Если бы я заранее знал об этой простой статистике, я бы не воспринимал в штыки попытки работодателей задавать мне по кругу одни и те же тривиальные вопросы. Для меня эта простая, но правдивая статистика стала большим сюрпризом.
Начало собеседования. Тимлид просит рассказать о себе, рассказывает о нашем проекте. Беседа ладится, по всем параметрам — наш кандидат. Разговор затянулся, кандидат рассказал кучу профессиональных историй, мы уже начали строить планы по захвату Вселенной! И вдруг одна странная реплика. «Стоп! — подумал я. — Давайте-ка я спрошу его о чем-то простом.» И задал ему вопрос, как устроены слайсы в Go. Дальше был полный облом по всем простейшим вещам. Только что мы разговаривали про нагрузочное и интеграционное тестирование, и, оказывается, он не знаем что такое стек, или структура данных, или… Да, я реально разговаривал с людьми, которые не знают, что такое рекурсия и стек!
Потом столкнулись с таким во второй раз. Было очень больно.
После этого мы приняли решение начинать с азов, с простейших вещей, независимо от того, что кандидат написал в анкете. 30 минут вполне достаточно, чтобы принять решение — плавно и вежливо завершить беседу или продолжить общение дальше. Если кандидат продержался 30 минут и мы продолжаем разговаривать, значит, время потрачено не зря. Даже если он нам не подойдёт. Или мы ему. Даже если он не примет оффер и не будет с нами работать. Такая беседа почти наверняка будет интересной и взаимно полезной, приятной и неутомительной.
Поначалу было сложно в точности следовать правилу. Но, опалив брови еще парочку раз, пусть и не так сильно, мы влились в практику, и с моим тимлидом Денисом собрали отличную команду. Спасибо тебе, Денис, за бесценный опыт.
ейчас, работая в #CloudMTS, я вижу, что здесь применяется именно эта практика. Так или иначе, через ошибки все приходят к одним и тем же решениям. Это ещё раз подтверждает жизнеспособность используемого подхода.
От кого-то (возможно, от отца) я слышал такую легенду. Мол, когда Игорь Курчатов собирал команду и решал, кто будет с ним работать над сами-знаете-каким проектом, он лично принимал у кандидатов теорминимум. Возможно, это не так, ведь своим теорминимумом был знаменит Лев Ландау. А может быть, это правда. Это неважно.
Важно то, что нужно отчетливо понимать, для чего мы проводим собеседование. Какова цель? Что мы хотим выяснить? Моя история руководства малыми командами началась приблизительно в 2006 году. Оглядываясь назад сейчас, я понимаю, как точно и справедливо то, что я сейчас скажу.
Вы никогда не узнаете все о человеке за одно собеседование. Люди слишком многогранны, список удивительных недостатков, мешающих работать, может занять несколько страниц. Все это невозможно выявить на собеседовании. Если хорошенько копнуть, завалить каверзными вопросами можно каждого. Но окажется ли хорошим сотрудником тот, кто ответит на все ваши вопросы? Не факт.
Тогда зачем мы проводим собеседование? Собеседуясь на роль разработчика, я столкнулся, как уже говорил, с попыткой меня проэкзаменовать. И зачастую это делали люди с меньшим опытом. Когда я сам стал проводить собеседования, то поймал себя на желании экзаменовать и заваливать кандидата вопросами, столь сложными, насколько сильна его квалификация. Порой, если кандидат сильный, это начинает походить на игру «где же он сломается». Своеобразная попытка найти, что он не знает. Это все не то.
Я считаю, что цель собеседования — определить минимальную и достаточную профпригодность, ответить «да» или «нет». И все. Не оценивать. Не критиковать. Не осуждать. Но дать ответ на вопрос: он сможет держать равновесие? Ну и по софт скиллам — понять, является ли он здравомыслящим и приятным в общении. Да или нет. Тут вызывает уважение, как работает проверка СБ — они или пропускают, или нет.
Если кандидат не знает чего-то, что нам принципиально важно, — тогда нет. Но если мы начнем «гонять» его по актуальному для нас здесь и сейчас стеку, есть огромный шанс отфильтровать крутого специалиста, а вместо него взять того, кто просто работал с привычными для нас вещами.
Убежден, что собеседование не должно быть экзаменом или исследованием на предмет таких «пробелов». Нужно фокусироваться на тех вещах, которые кандидат абсолютно точно должен знать, без вариантов, незнание которых безусловно и автоматически влечет отказ. Все остальное не знать можно.
Часто сложно понять, подходит ли кандидат, достаточно ли он хорош. «Да» или «нет». Задачу можно сильно упростить, если переформулировать вопрос. Вместо того, чтобы пытаться оценить кандидата по какой-то шкале компетенции, спросите себя: «Он готов завтра выйти на работу к нам? Хватит ли у него подготовки?». Здесь дать дискретный ответ намного проще.
Кроме собеседования хорошо зарекомендовали себя и другие способы проверить профпригодность кандидата. Например, испытательный (и оплачиваемый) срок в одну-две недели. Работает великолепно. За две недели можно узнать больше, чем за собеседование, а у кандидата не появляется ощущения, что он делает бесплатную работу, как в случае с тестовым заданием.
Кстати о них. Хорошее тестовое задание иногда занимает и пару дней фуллтайм, после чего крайне обидно получить отказ или вовсе тишину в ответ. Есть отличный компромисс — попросить кандидата предоставить любой свой опенсорсный проект, посмотреть его и предложить доработать. Так мы убедимся, что это действительно его проект, а кандидату не будет жалко потратить на него свое время.
Существует популярная отговорка — «я работал под NDA, проектов нет». Это лукавство. Я сам много лет работал под NDA и тоже так думал. А сейчас оглядываюсь и вижу почти десяток петпроджектов. Надо просто вспомнить, что они были, и выложить в сеть.
Недостаток компетенции vs неспособность драйвить результаты
Мне довелось поработать с очень разными людьми — среди них были не только ИТ-шники, но и ребята из строительства и производства. Судя по моему опыту, есть люди небрежные. Есть аккуратные. А ещё есть люди-паровозы, которые делают быстрее и больше. Какое отношение это имеет к ИТ? Непосредственное.
Профессия программиста стала массовой и с каждым годом эта тенденция усиливается. Прошли те времена, когда программист был кем-то вроде доктора наук. Это осталось в прошлом вместе с перфокартами.
Уточнение для тех, кто не застал дискеты и перфокарты. 1985 год, новейший суперкомпьютер Cray-2, с жидкостным охлаждением:
Он обеспечивал пиковую производительность 1.9 GFLOPS.
iPhone 12 = 11_000 GFLOPS, в 5 тысяч раз больше, прямо в вашем кармане. Ни одна другая отрасль не дает таких возможностей, как ИТ, по прогрессу возможностей и их бытовой доступности. Говорят, что среднебюджетный смартфон имеет больше вычислительной мощности, чем было на всей планете в 1969 году. Это не значит, что их тогда было мало. Их было много. Но стало еще больше.
Есть компетенции, которые можно проверить на собеседовании. Но есть и те, которые проверить затруднительно. Компетентен ли кандидат, который «на пятерку» знает язык, отлично ответил на вопросы и всем понравился? Не факт. Потому что в программировании почти как в литературе. Знание языка программирования подобно знанию литературного языка, знание паттернов — знанию стилистических приемов. И можно точно сказать, что человек, который не умеет писать, профнепригоден.
Но наоборот это, увы, не работает. Если человек умеет писать, хорошо начитан, это не гарантирует, что он сможет сочинить роман или даже колонку в газету.
Каково решение? Например, дать кандидату отрефакторить и привести в порядок фрагмент, который, хоть и работает, но написан плохо. И посмотреть, что будет. Сможет ли он найти «кривизну»? При любом раскладе вы сможете сделать выводы. Но это уже история не про кандидата, а, скорее, про испытуемого.
Где-то видел такой совет: при прочих равных, нанимайте тех, кто лучше пишет. Это не значит, что нужно нанимать писателей. Дело в том, что тот, кто может написать связный текст, способен ясно выразить свои мысли коллегам, начальству, инвесторам, в документации, и… в коде. Ясное изложение текстом — признак ясных мыслей. Все просто.
Приведу пример. Допустим, есть идея перекрасить все пешеходные переходы в зеленый цвет. Абсурдно? Да. Имеет ли это значение? Нет. Попросите кандидата текстом описать преимущества и недостатки этой идеи и посмотрите, как он с этим справится.
Результат решения задачи поможет буквально «под микроскопом» рассмотреть сознание кандидата. Пусть не количественно, а качественно.
Однажды я нанял специалиста, в обязанности которого входили написание и поддержание документации по проектам. Не формальности всякие (что обычно техписы делают), а именно внутренние документы. Чтобы не было кучи салфеток с заметками и можно было зафиксировать на бумаге «ту схему, нарисованную мелом на стене». К сожалению, оказалось, что человек физически не способен самостоятельно написать более 500 байт текста. То же самое применимо и к задаче нарисовать схему. Ясное изложение схемами — признак ясного мышления и способности излагать мысли. Это важно.
Существует мнение, что «наши» разработчики по определению знают лучше. Выражается это в повсеместной практике приглашать на собеседование тех специалистов, которые должны оценить кандидата. А что если кандидат обладает не меньшей экспертизой, чем те, кто его собеседует, но придерживается иных взглядов? Очевидно, у собеседователя будет негативный байас по отношению к кандидату. Как любой байас, это плохо, потому что необъективно.
Избавиться от этого сложно и не всегда нужно. Но важно помнить, что он есть. Как и риск, что коллеги отсекут все новое/непривычное/отличающееся, а к вам в компанию попадет не крутой спец, а человек с похожими взглядами. Пример: если React фронт собеседует фронта, а собеседуемый осторожно говорит, что «вообще-то React — не торт», скорее всего, работу он не получит. А вдруг React и правда так себе?
Мне довелось работать с Антоном Романюком, отличным бизнес-аналитиком, и он буквально «ломал» задачу, которой я занимался. Он нашел столько кейсов и граничных случаев, описал все это так, как не сделал бы тестировщик или кто-либо другой. Когда мне казалось, что «ну все, теперь чисто», он приходил и говорил «а что если вот тут — вот так?». Это было очень круто. На выходе получился безупречно работающий продукт с отличной документацией, выверенной, как юридический документ.
Бизнес-аналитика очень важна. Даже если этой должности нет, в каждой команде обязательно должен быть кто-то, несущий бремя аналитика. Часто это product owner, или РП, или даже простой разработчик. Ведь должность аналитика бывает довольно редко, а если и есть, под маской аналитика может скрываться продвинутый техпис. Я сталкивался со случаями, когда роль бизнес-аналитика отчасти брал на себя дизайнер. Неожиданно, правда?
Я считаю, в каждой команде должен быть кто-то, кто обладает способностью погрузиться в задачу предметно, глубоко и комплексно, понять вводные, упорядочить их в воображении и кристально четко видеть, что должно получиться. Сформулировать это понятно и доступно для других членов команды. Если в команде более одного человека с такой способностью, мы получим жаркие споры и дискуссии. Это неплохо! Но если нет ни одного, проект будет пробуксовывать даже с самыми сильными разработчиками.
Кроме всего этого, кто-то еще должен брать на себя груз ответственности. Человек, который на вопрос «это кто так придумал?» или «это кто так сказал?», сможет ответить «я». Есть люди которые боятся взять на себя ответственность, но бывает и наоборот. Если команда слаженная и построенная на доверии, выстроить взаимоотношения можно так, что аналитику делает один, а говорит «я так решил» и отстаивает выработанную внутри команды точку зрения другой. Такое взаимное дополнение.
Выше я писал о том, что собеседование необходимо начинать с азов. Напомню мои тезисы:
Этот список вопросов не исчерпывающий. Здесь есть как очень простые (например, «что есть стек?», потому что я видел тех, кто этого не знает), так и более хитрые. Use at your discretion, как говорится. Для себя я понял, что держать его открытым во время собеседования достаточно удобно. И после каждой встречи с кандидатами я дополняю его чем-то новым.
Начинайте с простых вопросов, чтобы прощупать уровень. По возможности переходите к сложным. Практика показывает, что сильные специалисты даже на простых вопросах расскажут что-то интересное.
Помните самые главные правила:
— Type switch
— Reflection
— Что есть слайсы?
— Что есть массивы?
— Три способа создать слайс? Создать слайс с размером 0 и емкостью N?
— Слайсы передаются в функцию по указателю, по значению или как-то еще?
— Append — пожалуйста, расскажи, как это напишешь? Как это работает? Насколько увеличится массив? Капасити пустого слайса? Аппенд к очень большим слайсам?
— Удалить элемент слева (в начале)? В середине?
— Есть бесконечный цикл, новые элементы аппендятся, первый элемент постоянно удаляется.
— Как много памяти съест такой слайс со временем (рассказать в деталях)?
— Вы передаете слайс в функцию, аппендите элемент и возвращаете слайс обратно —будет ли возвращенный слайс иметь тот же самый нижестоящий массив?
— Вы передаете слайс в функцию, аппендите элемент и возвращаете слайс обратно — будет ли возвращенный слайс использовать тот же нижележащий массив, что и оригинальный слайс? (детали)
— Есть слайс s1 с 50 элементами. Ты берешь s2=s1[30:40], затем анмаршалишь JSON в s2.
— Можно ли ожидать, что элементы 30..40 в s1 проапдейтятся, или что произойдет?
—Можно ли взять пойнтер на элемент слайса? Почему?
— Иммутабельность
— Руны
— Как итерировать по рунам?
— Оверхед использования рун, и вообще анализ в деталях
— Что такое горутины, потоки? Сколько и каких создается по умолчанию?
— Что они из себя представляют? Как много памяти занимают? Что если нужно больше стекового пространства?
— Как горутины мапятся на потоки ОС и на ядра процессора?
— Можно ли принудительно завершить горутину извне ее? Хорошо, вам правда это нужно, как вы решите эту задачу?
— Могут ли быть утечки горутин? Возможно ли это на практике? Приведите пример, как это может произойти и как вы будете устранять причину?
— У вас есть канал, из которого читаете, и некоторая блокирующая операция ввода-вывода, например сетевой сокет. Расскажите, как вы сможете объединить обе операции чтения в один общий цикл, так что бы не было ситуации блокировки и игнорирования данных в канале?
— Еще раз — что есть каналы по сути, какие бывают (два вида)?
— Вы пишете в небуферизированный канал, из которого никто не читает — что произойдет?
— Что такое блокировка (по существу)?
— У вас есть канал, несколько горутин читают из него. Вы записываете сообщение в канал.
— Какая горутина получит его?
— Что делать, если вам нужно, чтобы получили все?
— Что если количество читающих горутин переменное, как вы решите эту задачу?
— Что произойдет, если вы будете читать из закрытого канала?
— Как это может быть с пользой использовано? Есть ли стандартные библиотеки языка, работа которых построена на этом поведении каналов?
— Что произойдет, если вы попытаетесь записать в закрытый канал?
— Хорошо, но предположим, что вам нужно точно убедиться, что этого не произойдёт. Как вы поступите, есть ли какие-то методологии по этому поводу? Предположим вы не можете ничего гарантировать, но как вам обезопаситься от паники при записи в канал?
— Range над каналом
— Вы записали некоторые данные в буферизованный канал, и закрыли его. Можете ли вы прочитать эти данные обратно?
— У вас есть канал и вы хотите посылать в него данные только в том случае, если он готов их принять. Вы не можете позволить себе блокироваться и ждать записи. Как вы поступите?
— Опишите два или три варианта, как можно поступить, и сравните их. Что если канал не буферизован?
— Вы можете позволить себе заблокироваться на операции с каналом, но не более чем на 5 сек — как вы это реализуете?
— У вас есть библиотечная блокирующаяся функция, и без таймаута, но вы не можете себе позволить блокироваться без таймаута. Как вы сделаете обертку над ней, чтобы обеспечить таймаут?
— Можно ли определить, что канал полон?
— А можно ли определить, что он пуст? А если у нас есть канал для передачи данных, и перед завершением горутины хотим убедиться, что он пуст. Каков корректный способ это обеспечить?
— Почему “Uber best practices” рекомендует устанавливать емкость всех буферизованных каналов в 1 или иначе очень хорошо подумать, если там любая другая цифра? С чем это связано?
— Можно ли изменить размер буфера канала?
— Хорошо, вам очень это нужно, как вы реализуете это?
— Какие виды данных можно передавать через каналы? Можно ли передать другой канал? Пустую структуру? Зачем это может быть нужно?
— Всегда ли эффективнее передавать через каналы данные по указателю, или по значению — проведите сравнение и анализ.
— Как можно имплементировать RPC поверх каналов? То есть как коммуницировать с N горутин и получать ответы асинхронно от каждой отдельно?
— Как реализовать приоритезацию среди набора каналов? (Это самый хитрый вопрос. Если кандидат успешно расскажет как — он молодец.)
— Что такое waitgroups?
— Мьютексы — что это, что под капотом, какие виды бывают?
— Контексты: виды контекстов? Какой от них прок? Предположим, контекстов нет, — как вы имплементируете их сами? Как остановить net/http сервер?
— Семафоры и мьютексы: как имплементировать семафор с помощью канала? Как использовать канал вместо мьютекса?
— Мьютексы vs каналы: что лучше, что по этому поводу говорит «официальный Го» и что типично в проектах? Преимущества и недостатки — провести анализ-сравнение. Какие еще есть средства взаимодействия (перечислить хотя бы еще два)?
— Deadlocks: что представляют собой, как их детектировать, как понять, что это случилось? Как искать причину, дебажить? Как с ними бороться, стратегии по предотвращению? Как должна вести себя программа, если это произошло? Могут ли быть при использовании каналов?
Могут ли быть при использовании внешних ресурсов? Является ли умышленная блокировка горутины дедлоком? Привести примеры, как сделать дедлок в Go.
— Что такое гонки? [Задаем все те же вопросы, что и про дедлоки]
— Что это такое и как он работает?
— Можно ли его остановить, отключить, форсировать выполнение?
— Можно ли так написать программу, чтобы сборщику нечего было делать, или хотя бы минимизировать его работу? Какие паттерны наоборот приводят к избыточной нагрузке на сборщик?
— Стек vs хип (куча).
— Аллокация в стеке или на куче — от чего это зависит, как на это можно влиять? Escape analysis?
— Как мониторить циклы сборщик и расходование памяти? Каковы характерные графики?
— Как понять, что у вас утечка памяти?
— Как утечку дебажить (искать причину)?
— Как отследить утечку горутин? Пример — как такое может случиться? Как посмотреть количество горутин?
— vs. hash set?
— Что такое хэш-функция? … (а здесь место вашему воображению, читатель — см. комментарий в начале списка!)
— Embedding?
— Interfaces?
— “Exported” vs “not exported”?
— … (а здесь место вашему воображение, читатель — см. комментарий в начале списка!)
— Как создать новую ошибку?
— Новый тип?
— Проще, например, из строки?
— Как отследить, что возвращается конкретная ошибка?
— error.Is(), error.As();
— %w в формате строки?
— Управление зависимостями.
— Go mod.
— Вендоринг зависимостей.
— Проксирование и кэширование.
— Использование кэширования как неявного вендоринга.
— Чем модуль отличается от пакета?
— Допускает ли Go циклические импорт? Почему?
— Нам нужен циклический импорт — что делать?
— Использование интерфейсов для инверсии зависимостей?
— Способы организации кода?
— Генерация?
— Где используется?
— Как еще используется, кроме grpc?
— Реляционные?
— Нереляционные?
— Какова разница? Можно ли все виды задач решить в одном или другом классе БД?
— Уровни изоляции данных: Read uncommitted? Read committed? Repeatable read? Serializable?
— Consistency?
— Eventual consistency?
— Индексы — какие бывают? По назначению? Внутреннее устройство? Имплементация внутри, какие бывают варианты имплементаций? Индексы для геоданных?
— Шардирование?
— Мастер / слейв?
— Какие еще варианты бывают?
— Ограничения и сравнительный анализ?
— Инструменты?
— Сплит брейн в БД?
—Какие библиотеки вы используете (по каждой БД которую говорит что использовал (способ проверить использовал ли — если нет, сразу тут падает))?
—Отличия, особенности, и т.д.?
— Предназначение pgbouncer?
— Типы пуллинга?
— Ограничения?
— Производительность?
— Клиентский пуллинг в Го?
— OpenAPI, Swagger?
— Чем REST отличается от RPC?
— Может ли REST быть имплементирован не поверх HTTP? С примером?
— Возможно ли кэшировать REST? RPC?
— Балансировка нагрузки, RPC vs. REST?
— RESTful, REST-like — что это значит?
— Что это, чем отличается (кроме использования protobuf)?
— Особенности балансировки?
— push или pull?
— Режимы доставки at least once, at most once, exactly once?
— А вообще возможен ли 1= (exactly once)?
— Что такое персистентность?
— Расскажите о идемпотентности?
— Расскажите о split brain?
— Multicast / fanout, job distribution?
— Продолжите список
— Партиции
— Оффсеты
— Персистентность
— Consumer groups
— Наиболее распространенные библиотеки, и расскажите об опыте использования?
Секция 7, инфраструктура и архитектура
— Что такое Layers?
— Что такое Containers?
— Монолит vs микросервисы?
— Стоит ли делать новый продукт монолитным — преимущества и недостатки?
— Как монолит может упереться в потолок производительности, и что делать?
— Какие могут быть подходы при распиле монолита на микросервисы?
— Синхронное?
— Асинхронное?
— Событийное взаимодействие?
— Сага, два вида. Конечный автомат, персистизация состояния (в контексте оркестрационной саги)?
— 2PC?
— Eventual consistency vs. strict consistency — детали?
— CQRS, event sourcing?
— Audit log?
— Варианты интеграции, плюсы и минусы?
— B-tree?
— Trie, prefix tree?
— Другие виды?
В одной статье на Хабре уже рассказывали про оптимизацию процесса найма. Автор говорил, что для каждой компании и команды, для каждого тимлида и продакт оунера в разные моменты времени оптимальными могут быть разные способы. Предлагаю на этом и закончить.
Начал я этим заниматься ещё на предыдущем месте работы, где мы с тимлидом собирали новую команду. С тех пор прошло уже N лет, практика продолжилась, и после очередного собеседования я решил упорядочить свои знания. Кто-то считает, что от собеседований вообще толку нет, а кто-то наоборот (не будем показывать пальцем) проводит их в 3-5 раундов. Я уверен, что собеседования нужны, но важно четко понимать, зачем именно.
На всякий случай уточню: в статье речь пойдет не столько про конкретные вопросы (хотя они тоже будут), сколько про выработанную мной методику и принципы, которыми я руководствуюсь, задавая те или иные вопросы.
Еще я поделюсь неожиданными впечатлениями от ситуации, когда оказался «по ту сторону», лайфхаками, фейлами и неплохо зарекомендовавшими себя практиками. Про soft skills тут ничего не будет — это отдельная важная тема. Прежде всего мы затронем вопрос профпригодности, определения ее наличия или отсутствия. Во второй половине статьи приведу собственный список вопросов, переведенный на русский, с комментариями.
Зачем вообще нужно техническое собеседование
Ниже мы обязательно затронем эту тему подробнее, а сейчас предлагаю зафиксировать тезис. Я считаю, что техническое собеседование призвано дать понимание, достаточно ли профпригоден кандидат, чтобы приступить к работе завтра. Да или нет.
Здесь стоит уточнить, какие ошибки собеседующий разработчик может с большой долей вероятности совершить.
- Спрашивать про различные хаки, ноу-хау и хитрости
- Проверять специфичные знания
Основная задача — проверить базовую профпригодность. Не более и не менее.
Поясню, что я имею в виду. Допустим, мы собеседуем кандидата в разработчики на языке Х и видим, что он его отлично знает. У меня есть огромнейший бэкграунд работы с конечными автоматами (машинами состояний) — знаю о них больше, чем написано в университетском курсе. Я могу спросить кандидата: стоит ли выражать состояния целым числом, числом с плавающей точкой или строкой, какие плюсы и минусы есть? Мы сломали много копий на этом, и для меня ответ очевиден.
Нужно ли спрашивать об этом кандидата? Нет. Потому что это никакого отношения к профпригодности не имеет. Даже если нам с этим работать. Зато есть шанс, что кандидат на предыдущей работе был в команде, где это было «в эфире», слов нахватался, на вопрос ответит, хотя на самом деле как специалист слабенький. Welcome false positive.
- Искать человека-энциклопедию
Приведу еще один вариант «плохого» вопроса. Например, мы собеседуем разработчика на Go и просим его рассказать, как сделать семафор с помощью канала. Почему этот вопрос плохой?
- Во-первых, использование семафоров нетипично для разработки на Go, не идиоматично. Семафоров не было в стандартной библиотеке, они не используются в идиоматичной кодовой базе Go. Они, как правило, не нужны в прикладной работе.
- Во-вторых, сделать семафор с помощью канала довольно просто, но это хак в чистом виде. Ведь мы эмулируем переменную состояний с помощью очереди, а это явно не классический семафор.
- В-третьих, если так случилось, что кандидат где-то в интернете прочитал про этот хак, он легко ответит. Но это ничего не скажет о его профпригодности. Welcome false positive again. И наоборот — даже вполне профпригодный кандидат затруднится с ответом, если хака не знает. То же самое с вопросом, как использовать канал вместо мьютекса в Go.
Что такое «профпригодность»
Как понять, кто вам нужен? Заранее составьте список того, что точно должен знать кандидат как свои пять пальцев. И если он этих вещей не знает — вы его брать точно не будете.
Например, если мы берем разработчика на Go и его знания каналов или слайсов находятся на уровне «прочитал два раза, один раз попробовал», вряд ли он нам подойдет. Наверное, такие вещи он должен знать так, чтобы с ходу ответить на любой заковыристый вопрос, даже если его разбудить среди ночи.
А что делать, если мы работаем с брокером сообщений Х, а кандидат про него ничего не знает? Повод ли это его не брать или даже просто поставить минус? Уверен, что нет.
Как я уже говорил выше про такие вопросы:
Если знает — это плюс. Если не знает — это вообще ни о чем не говорит.
А вот по тем вопросам, которые мы определили как «профпригодность», знание должно быть 100% и абсолютное. Каждая команда сама должна определить, что это будет за перечень.
Защита от читерства и подготовки по списку
Окей. А если потенциальный соискатель прочитает эту статью, вопросы, подготовится и обманет собеседование. Возможно ли такое?
Опасаться не стоит. Есть железобетонная методика выявления того, насколько человек глубоко знает предмет. Называется она Asymmetric Information Management technique или просто AIM technique — техника ассиметричного управления информацией.
Если коротко, принцип достаточно простой: когда люди рассказывают о том, что действительно было, и/или разбираются в предмете, им нравится погружаться в детали. И наоборот — избегают погружения, когда знакомы с темой поверхностно или рассказывают небылицы. Техника с успехом применяется правоохранительными органами, и некоторые говорят, что работает она лучше полиграфа.
Применяет ее и Илон Маск. Его знаменитый «главный вопрос» на собеседованиях звучит так:Вопросы нужно задавать так, чтобы постоянно понимать, а правда ли собеседуемый понимает, о чем говорит, или он заучил ответ. При малейших сомнениях копаем вглубь. Да, это непросто, поэтому вопросы обязательно должен задавать тот человек, кто при необходимости способен отойти от чек-листа и погрузиться в детали.
“Tell me about some of the most difficult problems you worked on and how you solved them.”
«Расскажите о самой сложной проблеме, над которой вам доводилось работать, и как вы преодолели сложности.»
Однажды мы собеседовали кандидата на роль разработчика Go и позволили одному из коллег попробовать себя в роли интервьюера, я же просто слушал. Он задавал достаточно тривиальные вопросы «по списку» — например, про слайсы в Go — а кандидат уверенно отвечал. На фоне было слышно, как он гуглит. Минут через 7 я решил вмешаться и на тривиальных вещах про слайсы просто стал копать в детали. На втором вопросе кандидат просто повесил трубку. Мы даже сначала подумали, что это обрыв связи, так все неожиданно произошло. Но нет. Он видимо, что-то понял :)
Так что копайте вглубь, в детали, и обман не пройдет.
Первый раз «по ту сторону»
Я очень долго никуда не собеседовался. Хотя «долго» — понятие относительное. 15+ лет, это долго? Естественно, пропадает навык. Вообще это парадокс — только ты выработал навык находить работу, нашел ее, и он становится больше не нужен. А пока работу не ищешь, скилл атрофируется.
Почему я не искал работу? Потому что переходил из одного удивительного проекта в другой, было не до этого. Плюс мой технологический стек отличался от того, который был востребован на рынке.
Почему я стал искать работу в ±2019 году? Во-первых, ни один из моих стартапов не принес мне миллиарда. Начали подходить к завершению обязательства по одному интересному, но малобюджетному проекту, а зарабатывать больше хотелось (к тому же я женился). Во-вторых, к моему немалому удивлению неожиданно обнаружилось, что каким-то совершенно непостижимым образом одна «никому не нужная» технология из моего стека является неожиданно очень даже нужной. Java куда-то начала сдавать, а крупные компании «полюбили» Go, который я полным ходом использовал для промышленных проектов. И я решил попробовать — почему бы и нет?
Первое же собеседование поставило меня в тупик. Мне было совершенно непонятно, зачем мне задавать вот эти все вопросы, если можно посмотреть на фото работающих продуктов? Зачем спрашивать, как устроен слайс в Go, если человек пришел ногами и принес стопку фот того, что работает в проде? Было непонятно.
И вот спустя месяц меня просят присоединиться к собеседованию кандидата на Go. Для подстраховки, ну… или не знаю зачем. Я принял инициативу, и коллеги потом сказали, что «это было круто, уровень как в одной-большой-компании» (это был приятный комплимент, хотя я, честно говоря, не знаю, как там у этой компании). С тех пор я стал проводить их всегда.
Я почти сразу получил ответ, зачем задавать тривиальные вопросы. Очень просто. Примерно 9 из 10 кандидатов не знали языка. Они прочитали о нем в интернете, но что-то конкретное сделать не могли. Если бы я заранее знал об этой простой статистике, я бы не воспринимал в штыки попытки работодателей задавать мне по кругу одни и те же тривиальные вопросы. Для меня эта простая, но правдивая статистика стала большим сюрпризом.
Как мы обжигались
Начало собеседования. Тимлид просит рассказать о себе, рассказывает о нашем проекте. Беседа ладится, по всем параметрам — наш кандидат. Разговор затянулся, кандидат рассказал кучу профессиональных историй, мы уже начали строить планы по захвату Вселенной! И вдруг одна странная реплика. «Стоп! — подумал я. — Давайте-ка я спрошу его о чем-то простом.» И задал ему вопрос, как устроены слайсы в Go. Дальше был полный облом по всем простейшим вещам. Только что мы разговаривали про нагрузочное и интеграционное тестирование, и, оказывается, он не знаем что такое стек, или структура данных, или… Да, я реально разговаривал с людьми, которые не знают, что такое рекурсия и стек!
Потом столкнулись с таким во второй раз. Было очень больно.
После этого мы приняли решение начинать с азов, с простейших вещей, независимо от того, что кандидат написал в анкете. 30 минут вполне достаточно, чтобы принять решение — плавно и вежливо завершить беседу или продолжить общение дальше. Если кандидат продержался 30 минут и мы продолжаем разговаривать, значит, время потрачено не зря. Даже если он нам не подойдёт. Или мы ему. Даже если он не примет оффер и не будет с нами работать. Такая беседа почти наверняка будет интересной и взаимно полезной, приятной и неутомительной.
Поначалу было сложно в точности следовать правилу. Но, опалив брови еще парочку раз, пусть и не так сильно, мы влились в практику, и с моим тимлидом Денисом собрали отличную команду. Спасибо тебе, Денис, за бесценный опыт.
Практика, к которой мы пришли, оказалась общепринятой
ейчас, работая в #CloudMTS, я вижу, что здесь применяется именно эта практика. Так или иначе, через ошибки все приходят к одним и тем же решениям. Это ещё раз подтверждает жизнеспособность используемого подхода.
Цель — да или нет. Программа минимум
От кого-то (возможно, от отца) я слышал такую легенду. Мол, когда Игорь Курчатов собирал команду и решал, кто будет с ним работать над сами-знаете-каким проектом, он лично принимал у кандидатов теорминимум. Возможно, это не так, ведь своим теорминимумом был знаменит Лев Ландау. А может быть, это правда. Это неважно.
Важно то, что нужно отчетливо понимать, для чего мы проводим собеседование. Какова цель? Что мы хотим выяснить? Моя история руководства малыми командами началась приблизительно в 2006 году. Оглядываясь назад сейчас, я понимаю, как точно и справедливо то, что я сейчас скажу.
Не надо устраивать из собеседования экзамен.
Вы никогда не узнаете все о человеке за одно собеседование. Люди слишком многогранны, список удивительных недостатков, мешающих работать, может занять несколько страниц. Все это невозможно выявить на собеседовании. Если хорошенько копнуть, завалить каверзными вопросами можно каждого. Но окажется ли хорошим сотрудником тот, кто ответит на все ваши вопросы? Не факт.
Тогда зачем мы проводим собеседование? Собеседуясь на роль разработчика, я столкнулся, как уже говорил, с попыткой меня проэкзаменовать. И зачастую это делали люди с меньшим опытом. Когда я сам стал проводить собеседования, то поймал себя на желании экзаменовать и заваливать кандидата вопросами, столь сложными, насколько сильна его квалификация. Порой, если кандидат сильный, это начинает походить на игру «где же он сломается». Своеобразная попытка найти, что он не знает. Это все не то.
Мы все чего-то не знаем.
Я считаю, что цель собеседования — определить минимальную и достаточную профпригодность, ответить «да» или «нет». И все. Не оценивать. Не критиковать. Не осуждать. Но дать ответ на вопрос: он сможет держать равновесие? Ну и по софт скиллам — понять, является ли он здравомыслящим и приятным в общении. Да или нет. Тут вызывает уважение, как работает проверка СБ — они или пропускают, или нет.
Если кандидат не знает чего-то, что нам принципиально важно, — тогда нет. Но если мы начнем «гонять» его по актуальному для нас здесь и сейчас стеку, есть огромный шанс отфильтровать крутого специалиста, а вместо него взять того, кто просто работал с привычными для нас вещами.
Убежден, что собеседование не должно быть экзаменом или исследованием на предмет таких «пробелов». Нужно фокусироваться на тех вещах, которые кандидат абсолютно точно должен знать, без вариантов, незнание которых безусловно и автоматически влечет отказ. Все остальное не знать можно.
Часто сложно понять, подходит ли кандидат, достаточно ли он хорош. «Да» или «нет». Задачу можно сильно упростить, если переформулировать вопрос. Вместо того, чтобы пытаться оценить кандидата по какой-то шкале компетенции, спросите себя: «Он готов завтра выйти на работу к нам? Хватит ли у него подготовки?». Здесь дать дискретный ответ намного проще.
Другие способы и практики проверки кандидатов
Кроме собеседования хорошо зарекомендовали себя и другие способы проверить профпригодность кандидата. Например, испытательный (и оплачиваемый) срок в одну-две недели. Работает великолепно. За две недели можно узнать больше, чем за собеседование, а у кандидата не появляется ощущения, что он делает бесплатную работу, как в случае с тестовым заданием.
Кстати о них. Хорошее тестовое задание иногда занимает и пару дней фуллтайм, после чего крайне обидно получить отказ или вовсе тишину в ответ. Есть отличный компромисс — попросить кандидата предоставить любой свой опенсорсный проект, посмотреть его и предложить доработать. Так мы убедимся, что это действительно его проект, а кандидату не будет жалко потратить на него свое время.
Существует популярная отговорка — «я работал под NDA, проектов нет». Это лукавство. Я сам много лет работал под NDA и тоже так думал. А сейчас оглядываюсь и вижу почти десяток петпроджектов. Надо просто вспомнить, что они были, и выложить в сеть.
Недостаток компетенции vs неспособность драйвить результаты
Мне довелось поработать с очень разными людьми — среди них были не только ИТ-шники, но и ребята из строительства и производства. Судя по моему опыту, есть люди небрежные. Есть аккуратные. А ещё есть люди-паровозы, которые делают быстрее и больше. Какое отношение это имеет к ИТ? Непосредственное.
Профессия программиста стала массовой и с каждым годом эта тенденция усиливается. Прошли те времена, когда программист был кем-то вроде доктора наук. Это осталось в прошлом вместе с перфокартами.
Уточнение для тех, кто не застал дискеты и перфокарты. 1985 год, новейший суперкомпьютер Cray-2, с жидкостным охлаждением:
Он обеспечивал пиковую производительность 1.9 GFLOPS.
iPhone 12 = 11_000 GFLOPS, в 5 тысяч раз больше, прямо в вашем кармане. Ни одна другая отрасль не дает таких возможностей, как ИТ, по прогрессу возможностей и их бытовой доступности. Говорят, что среднебюджетный смартфон имеет больше вычислительной мощности, чем было на всей планете в 1969 году. Это не значит, что их тогда было мало. Их было много. Но стало еще больше.
Есть компетенции, которые можно проверить на собеседовании. Но есть и те, которые проверить затруднительно. Компетентен ли кандидат, который «на пятерку» знает язык, отлично ответил на вопросы и всем понравился? Не факт. Потому что в программировании почти как в литературе. Знание языка программирования подобно знанию литературного языка, знание паттернов — знанию стилистических приемов. И можно точно сказать, что человек, который не умеет писать, профнепригоден.
Но наоборот это, увы, не работает. Если человек умеет писать, хорошо начитан, это не гарантирует, что он сможет сочинить роман или даже колонку в газету.
Каково решение? Например, дать кандидату отрефакторить и привести в порядок фрагмент, который, хоть и работает, но написан плохо. И посмотреть, что будет. Сможет ли он найти «кривизну»? При любом раскладе вы сможете сделать выводы. Но это уже история не про кандидата, а, скорее, про испытуемого.
При прочих равных нанимать тех, кто лучше пишет
Где-то видел такой совет: при прочих равных, нанимайте тех, кто лучше пишет. Это не значит, что нужно нанимать писателей. Дело в том, что тот, кто может написать связный текст, способен ясно выразить свои мысли коллегам, начальству, инвесторам, в документации, и… в коде. Ясное изложение текстом — признак ясных мыслей. Все просто.
Приведу пример. Допустим, есть идея перекрасить все пешеходные переходы в зеленый цвет. Абсурдно? Да. Имеет ли это значение? Нет. Попросите кандидата текстом описать преимущества и недостатки этой идеи и посмотрите, как он с этим справится.
Результат решения задачи поможет буквально «под микроскопом» рассмотреть сознание кандидата. Пусть не количественно, а качественно.
Однажды я нанял специалиста, в обязанности которого входили написание и поддержание документации по проектам. Не формальности всякие (что обычно техписы делают), а именно внутренние документы. Чтобы не было кучи салфеток с заметками и можно было зафиксировать на бумаге «ту схему, нарисованную мелом на стене». К сожалению, оказалось, что человек физически не способен самостоятельно написать более 500 байт текста. То же самое применимо и к задаче нарисовать схему. Ясное изложение схемами — признак ясного мышления и способности излагать мысли. Это важно.
Байас — наши программисты по определению умнее тех, кого мы собеседуем (нет)
Существует мнение, что «наши» разработчики по определению знают лучше. Выражается это в повсеместной практике приглашать на собеседование тех специалистов, которые должны оценить кандидата. А что если кандидат обладает не меньшей экспертизой, чем те, кто его собеседует, но придерживается иных взглядов? Очевидно, у собеседователя будет негативный байас по отношению к кандидату. Как любой байас, это плохо, потому что необъективно.
Избавиться от этого сложно и не всегда нужно. Но важно помнить, что он есть. Как и риск, что коллеги отсекут все новое/непривычное/отличающееся, а к вам в компанию попадет не крутой спец, а человек с похожими взглядами. Пример: если React фронт собеседует фронта, а собеседуемый осторожно говорит, что «вообще-то React — не торт», скорее всего, работу он не получит. А вдруг React и правда так себе?
О бизнес-аналитике
Мне довелось работать с Антоном Романюком, отличным бизнес-аналитиком, и он буквально «ломал» задачу, которой я занимался. Он нашел столько кейсов и граничных случаев, описал все это так, как не сделал бы тестировщик или кто-либо другой. Когда мне казалось, что «ну все, теперь чисто», он приходил и говорил «а что если вот тут — вот так?». Это было очень круто. На выходе получился безупречно работающий продукт с отличной документацией, выверенной, как юридический документ.
Бизнес-аналитика очень важна. Даже если этой должности нет, в каждой команде обязательно должен быть кто-то, несущий бремя аналитика. Часто это product owner, или РП, или даже простой разработчик. Ведь должность аналитика бывает довольно редко, а если и есть, под маской аналитика может скрываться продвинутый техпис. Я сталкивался со случаями, когда роль бизнес-аналитика отчасти брал на себя дизайнер. Неожиданно, правда?
Я считаю, в каждой команде должен быть кто-то, кто обладает способностью погрузиться в задачу предметно, глубоко и комплексно, понять вводные, упорядочить их в воображении и кристально четко видеть, что должно получиться. Сформулировать это понятно и доступно для других членов команды. Если в команде более одного человека с такой способностью, мы получим жаркие споры и дискуссии. Это неплохо! Но если нет ни одного, проект будет пробуксовывать даже с самыми сильными разработчиками.
Кроме всего этого, кто-то еще должен брать на себя груз ответственности. Человек, который на вопрос «это кто так придумал?» или «это кто так сказал?», сможет ответить «я». Есть люди которые боятся взять на себя ответственность, но бывает и наоборот. Если команда слаженная и построенная на доверии, выстроить взаимоотношения можно так, что аналитику делает один, а говорит «я так решил» и отстаивает выработанную внутри команды точку зрения другой. Такое взаимное дополнение.
Мой список вопросов на русском с комментариями
Выше я писал о том, что собеседование необходимо начинать с азов. Напомню мои тезисы:
- Собеседование — не экзамен.
- Наша задача не в том, чтобы найти, чего кандидат не знает. Нам необходимо оценить его на предмет соответствия минимуму профпригодности (который можно заранее для себя определить).
- Начинать стоит с простых вопросов, чтобы не терять зря время если кандидат слаб, и переходить к более интересным, если кандидат силен.
Этот список вопросов не исчерпывающий. Здесь есть как очень простые (например, «что есть стек?», потому что я видел тех, кто этого не знает), так и более хитрые. Use at your discretion, как говорится. Для себя я понял, что держать его открытым во время собеседования достаточно удобно. И после каждой встречи с кандидатами я дополняю его чем-то новым.
Начинайте с простых вопросов, чтобы прощупать уровень. По возможности переходите к сложным. Практика показывает, что сильные специалисты даже на простых вопросах расскажут что-то интересное.
Помните самые главные правила:
- Составьте заранее список того, что есть «профпригодность» для этой роли и этой команды. Кандидат по этому списку что-то не знает? Ок, один раз можно сделать поблажку, но если два пункта мимо — однозначно нет. Это «килл лист», фильтр, но не способ оценить уровень.
- По тем вопросам, которые не входят в килл-лист, руководствуйтесь правилом: если знает — это плюс, если не знает — это ничего не значит.
- Когда чувствуете, что вас водят за нос — на ровном месте начинайте копать в детали, задавать более глубокие и уточняющие вопросы. Правда моментально проявляется, как вода на песке.
Вопросы ниже не покрывают все темы. Например, про мапы можно было бы поговорить не меньше, чем про слайсы или конкурентность — этого здесь нет нарочно.
Некоторые вопросы дублируются — it’s intentional, так что список можно использовать не только сверху-вниз, но с любого места рандомно.
Прежде всего, я хочу поделиться собственной шпаргалкой. Пустые места и прогалы вы можете сами дополнить. Да и вообще, если дать полный список, на собеседовании не останется интриги!
Секция 1, системный минимум, начальные вопросы
- Что такое стек? Что такое рекурсия?
- Как в Go вы можете повлиять, попадет ли что-то в стек или хип (кучу)?
- Что такое структура данных? Что такое переменная? Что есть регистр? Указатель?
- Поток ОС, процесс ОС — что такое, чем отличается горутина? Расскажите о памяти в данном контексте?
- Что такое контейнеры, ВМ? отличие ВМ от контейнера, виды гипервизоров?
- Как ОС управляет памятью? Страницы, виртуальная память?
- Иерархия памяти. Фенсинг, барьеры, зачем?
- Ядро ОС, syscalls, cgroups, systemd; systemd vs. docker?
- Как убить процесс Linux по имени? Еще какие способы? Недостатки и преимущества? Что такое jobs?
- Как сконфигурировать доступ SSH по ключу на свежепроинсталлированный Linux?
- Как посмотреть логи в Linux? Второй способ?
- Что такое дедлоки?
- Race conditions?
- Идемпотентность?
Секция 2, минимум по Golang
- Синтаксис switch — чем отличается от других языков?
- Система типов
— Type switch
— Reflection
- Slices (90% кандидатов отсеиваются на этих вопросах)
— Что есть слайсы?
— Что есть массивы?
— Три способа создать слайс? Создать слайс с размером 0 и емкостью N?
— Слайсы передаются в функцию по указателю, по значению или как-то еще?
— Append — пожалуйста, расскажи, как это напишешь? Как это работает? Насколько увеличится массив? Капасити пустого слайса? Аппенд к очень большим слайсам?
— Удалить элемент слева (в начале)? В середине?
— Есть бесконечный цикл, новые элементы аппендятся, первый элемент постоянно удаляется.
— Как много памяти съест такой слайс со временем (рассказать в деталях)?
— Вы передаете слайс в функцию, аппендите элемент и возвращаете слайс обратно —будет ли возвращенный слайс иметь тот же самый нижестоящий массив?
— Вы передаете слайс в функцию, аппендите элемент и возвращаете слайс обратно — будет ли возвращенный слайс использовать тот же нижележащий массив, что и оригинальный слайс? (детали)
— Есть слайс s1 с 50 элементами. Ты берешь s2=s1[30:40], затем анмаршалишь JSON в s2.
— Можно ли ожидать, что элементы 30..40 в s1 проапдейтятся, или что произойдет?
—Можно ли взять пойнтер на элемент слайса? Почему?
- Строки в Го
— Иммутабельность
— Руны
— Как итерировать по рунам?
— Оверхед использования рун, и вообще анализ в деталях
- Конкурентность (это еще одна тема, которую каждый кандидат должен предельно четко понимать; многие выучили мантру, что конкурентность не равно параллелизм, но нужно убедиться, что он правда понимает это, а не заучил формулу).
— Что такое горутины, потоки? Сколько и каких создается по умолчанию?
— Что они из себя представляют? Как много памяти занимают? Что если нужно больше стекового пространства?
— Как горутины мапятся на потоки ОС и на ядра процессора?
— Можно ли принудительно завершить горутину извне ее? Хорошо, вам правда это нужно, как вы решите эту задачу?
— Могут ли быть утечки горутин? Возможно ли это на практике? Приведите пример, как это может произойти и как вы будете устранять причину?
- Каналы (продолжение про конкурентность)
— У вас есть канал, из которого читаете, и некоторая блокирующая операция ввода-вывода, например сетевой сокет. Расскажите, как вы сможете объединить обе операции чтения в один общий цикл, так что бы не было ситуации блокировки и игнорирования данных в канале?
— Еще раз — что есть каналы по сути, какие бывают (два вида)?
— Вы пишете в небуферизированный канал, из которого никто не читает — что произойдет?
— Что такое блокировка (по существу)?
— У вас есть канал, несколько горутин читают из него. Вы записываете сообщение в канал.
— Какая горутина получит его?
— Что делать, если вам нужно, чтобы получили все?
— Что если количество читающих горутин переменное, как вы решите эту задачу?
— Что произойдет, если вы будете читать из закрытого канала?
— Как это может быть с пользой использовано? Есть ли стандартные библиотеки языка, работа которых построена на этом поведении каналов?
— Что произойдет, если вы попытаетесь записать в закрытый канал?
— Хорошо, но предположим, что вам нужно точно убедиться, что этого не произойдёт. Как вы поступите, есть ли какие-то методологии по этому поводу? Предположим вы не можете ничего гарантировать, но как вам обезопаситься от паники при записи в канал?
— Range над каналом
— Вы записали некоторые данные в буферизованный канал, и закрыли его. Можете ли вы прочитать эти данные обратно?
— У вас есть канал и вы хотите посылать в него данные только в том случае, если он готов их принять. Вы не можете позволить себе блокироваться и ждать записи. Как вы поступите?
— Опишите два или три варианта, как можно поступить, и сравните их. Что если канал не буферизован?
— Вы можете позволить себе заблокироваться на операции с каналом, но не более чем на 5 сек — как вы это реализуете?
— У вас есть библиотечная блокирующаяся функция, и без таймаута, но вы не можете себе позволить блокироваться без таймаута. Как вы сделаете обертку над ней, чтобы обеспечить таймаут?
— Можно ли определить, что канал полон?
— А можно ли определить, что он пуст? А если у нас есть канал для передачи данных, и перед завершением горутины хотим убедиться, что он пуст. Каков корректный способ это обеспечить?
— Почему “Uber best practices” рекомендует устанавливать емкость всех буферизованных каналов в 1 или иначе очень хорошо подумать, если там любая другая цифра? С чем это связано?
— Можно ли изменить размер буфера канала?
— Хорошо, вам очень это нужно, как вы реализуете это?
— Какие виды данных можно передавать через каналы? Можно ли передать другой канал? Пустую структуру? Зачем это может быть нужно?
— Всегда ли эффективнее передавать через каналы данные по указателю, или по значению — проведите сравнение и анализ.
— Как можно имплементировать RPC поверх каналов? То есть как коммуницировать с N горутин и получать ответы асинхронно от каждой отдельно?
— Как реализовать приоритезацию среди набора каналов? (Это самый хитрый вопрос. Если кандидат успешно расскажет как — он молодец.)
- Синхронизация (конкурентность, часть 3)
— Что такое waitgroups?
— Мьютексы — что это, что под капотом, какие виды бывают?
— Контексты: виды контекстов? Какой от них прок? Предположим, контекстов нет, — как вы имплементируете их сами? Как остановить net/http сервер?
— Семафоры и мьютексы: как имплементировать семафор с помощью канала? Как использовать канал вместо мьютекса?
— Мьютексы vs каналы: что лучше, что по этому поводу говорит «официальный Го» и что типично в проектах? Преимущества и недостатки — провести анализ-сравнение. Какие еще есть средства взаимодействия (перечислить хотя бы еще два)?
— Deadlocks: что представляют собой, как их детектировать, как понять, что это случилось? Как искать причину, дебажить? Как с ними бороться, стратегии по предотвращению? Как должна вести себя программа, если это произошло? Могут ли быть при использовании каналов?
Могут ли быть при использовании внешних ресурсов? Является ли умышленная блокировка горутины дедлоком? Привести примеры, как сделать дедлок в Go.
— Что такое гонки? [Задаем все те же вопросы, что и про дедлоки]
- Сборщик мусора и управление памятью
— Что это такое и как он работает?
— Можно ли его остановить, отключить, форсировать выполнение?
— Можно ли так написать программу, чтобы сборщику нечего было делать, или хотя бы минимизировать его работу? Какие паттерны наоборот приводят к избыточной нагрузке на сборщик?
— Стек vs хип (куча).
— Аллокация в стеке или на куче — от чего это зависит, как на это можно влиять? Escape analysis?
— Как мониторить циклы сборщик и расходование памяти? Каковы характерные графики?
— Как понять, что у вас утечка памяти?
— Как утечку дебажить (искать причину)?
— Как отследить утечку горутин? Пример — как такое может случиться? Как посмотреть количество горутин?
- Maps
— vs. hash set?
— Что такое хэш-функция? … (а здесь место вашему воображению, читатель — см. комментарий в начале списка!)
- ООП
— Embedding?
— Interfaces?
— “Exported” vs “not exported”?
— … (а здесь место вашему воображение, читатель — см. комментарий в начале списка!)
- Ошибка
— Как создать новую ошибку?
— Новый тип?
— Проще, например, из строки?
— Как отследить, что возвращается конкретная ошибка?
— error.Is(), error.As();
— %w в формате строки?
- Управление репозиториями, проектами и зависимостями
— Управление зависимостями.
— Go mod.
— Вендоринг зависимостей.
— Проксирование и кэширование.
— Использование кэширования как неявного вендоринга.
— Чем модуль отличается от пакета?
— Допускает ли Go циклические импорт? Почему?
— Нам нужен циклический импорт — что делать?
— Использование интерфейсов для инверсии зависимостей?
— Способы организации кода?
Секция 3, форматы данных
- JSON
- Формат gob — что это?
- XML
- YAML
- protobuf
— Генерация?
— Где используется?
— Как еще используется, кроме grpc?
Секция 4, базы данных
- Основное
— Реляционные?
— Нереляционные?
— Какова разница? Можно ли все виды задач решить в одном или другом классе БД?
— Уровни изоляции данных: Read uncommitted? Read committed? Repeatable read? Serializable?
- 2PC (заодно пусть расскажет что это): Задачка про транзакцию над несколькими внешними БД, можно пример про отпуск и билеты.
— Consistency?
— Eventual consistency?
— Индексы — какие бывают? По назначению? Внутреннее устройство? Имплементация внутри, какие бывают варианты имплементаций? Индексы для геоданных?
- Репликация
— Шардирование?
— Мастер / слейв?
— Какие еще варианты бывают?
— Ограничения и сравнительный анализ?
- Отказоустойчивость
— Инструменты?
— Сплит брейн в БД?
- Redis, Postgres, MongoDB, et al
—Какие библиотеки вы используете (по каждой БД которую говорит что использовал (способ проверить использовал ли — если нет, сразу тут падает))?
—Отличия, особенности, и т.д.?
- PostgreSQL
— Предназначение pgbouncer?
— Типы пуллинга?
— Ограничения?
— Производительность?
— Клиентский пуллинг в Го?
Секция 5, сети
- Что такое L2, L3, L4, L7? Детали и примеры.
- IP адреса, маски, DNS?
- VPN и бриджевание L2 или L3 — в чем разница?
- Что такое ARP-запрос?
- Вы вводите в строке браузера google.com и нажимаете Enter — расскажите за 3 минуты в деталях, что дальше будет происходить? (с этого можно начать)
- HTTP
- Как такой запрос выглядит?
- TCP?
- TLS?
- UDP?
- Расскажите о преимуществах и недостатках, проведите сравнительный анализ, приведите примеры, где использовали бы одно, а где другое.
- Что такое порты? А сокеты? В чем разница?
- Расскажите что такое RPC?
- Что такое REST?
— OpenAPI, Swagger?
— Чем REST отличается от RPC?
— Может ли REST быть имплементирован не поверх HTTP? С примером?
— Возможно ли кэшировать REST? RPC?
— Балансировка нагрузки, RPC vs. REST?
— RESTful, REST-like — что это значит?
- GRPC
— Что это, чем отличается (кроме использования protobuf)?
— Особенности балансировки?
Секция 6, брокеры, очереди сообщений
- Общее
— push или pull?
— Режимы доставки at least once, at most once, exactly once?
— А вообще возможен ли 1= (exactly once)?
— Что такое персистентность?
— Расскажите о идемпотентности?
— Расскажите о split brain?
- Паттерны
— Multicast / fanout, job distribution?
— Продолжите список
- Kafka
— Партиции
— Оффсеты
— Персистентность
— Consumer groups
— Наиболее распространенные библиотеки, и расскажите об опыте использования?
- AMQP / RabbitMQ (если он работал с ним)
- NATS (если он работал с ним)
- NATS Streaming / JetStream (если он работал с ним)
- и т.д.
Секция 7, инфраструктура и архитектура
- Docker
— Что такое Layers?
— Что такое Containers?
- Kubernetes (или альтернативы)?
- Шаблоны микросервисной архитектуры?
— Монолит vs микросервисы?
— Стоит ли делать новый продукт монолитным — преимущества и недостатки?
— Как монолит может упереться в потолок производительности, и что делать?
— Какие могут быть подходы при распиле монолита на микросервисы?
- Межсервисное взаимодействие
— Синхронное?
— Асинхронное?
— Событийное взаимодействие?
— Сага, два вида. Конечный автомат, персистизация состояния (в контексте оркестрационной саги)?
— 2PC?
— Eventual consistency vs. strict consistency — детали?
— CQRS, event sourcing?
— Audit log?
— Варианты интеграции, плюсы и минусы?
Секция 8, алгоритмы
- Деревья
— B-tree?
— Trie, prefix tree?
— Другие виды?
Подведем итоги
В одной статье на Хабре уже рассказывали про оптимизацию процесса найма. Автор говорил, что для каждой компании и команды, для каждого тимлида и продакт оунера в разные моменты времени оптимальными могут быть разные способы. Предлагаю на этом и закончить.
Главное, чтобы каждая команда была дружной и эффективной.