Каждый разработчик время от времени ищет работу и проходит собеседования. Кто-то хочет попробовать что-то новое, получить большую ЗП или попасть в компанию, в которую всегда мечтал. Не обошло это событие и меня стороной.
Посетив множество компаний, я решил поделиться наблюдениями о том, как чаще всего проходит набор специалистов, в том числе техническое собеседование и просто общение с потенциальными коллегами. И после предложить свои идеи по улучшению общепринятого процесса.
Чтобы в итоге собеседование не выглядело для соискателя как:
Статья в первую очередь будет полезна всем, кто ищет работу в среде iOS разработки или хоть как-то связан с набором IT специалистов: проводит технические собеседования или любые другие.
И добро пожаловать под кат.
Вступление
Хочу отметить, что считаю себя человеком результата. Любые действия, в том числе самообразование, должны быть направлены на достижение конкретной цели или решение определенной задачи. Когда доводилось проводить собеседование в своей компании, то всегда старался спросить нечто полезное на практике, понять как соискатель поведет себя в 'боевых действиях', что предпримет для реализации того или иного модуля, или как будет бороться с определенным багом.
Так вот, я был поражен тем, что из более чем десятка посещенных мною довольно крупных организаций, с офисами в центре, объемными секретаршами, плойки и прочими атрибутами пафосного офиса, абсолютно все спрашивают только начитку.
Нерафинированная 100% теория без какой-либо связи с практикой. Никто не поинтересовался как я размышляю, подхожу к задачам, как стал бы ловить нестандартные вылеты, искать причины плохой производительности в приложении и решать прочие будничные проблемы с которыми разработчик сталкивается каждый день. Всех интересовало только отличие ARC от MRC и разнообразная ни разу в жизни не понадобившаяся муть. Например: чем строение файла xib отличается от строения файла storyboard. Именно файла. Такая полезная вещь. Каждый день ковыряюсь в xml.
Это не значит, что меня везде послали и я пришел ныть на Хабр. В большинстве случаев все проходило позитивно, разве что за небольшим исключением. А если где-то и сталкивался с откровенным пробелом в знаниях, то к следующему собеседованию он уже был успешно освоен. И порой даже простой разговор с будущим руководством компенсировал не слишком удачно(на мой взгляд) пройденное техническое собеседование.
Эта статья могла бы стать обычным нытьем о несовершенстве мира, но я решил вынести максимум пользы и составить список вопросов, по которым можно реально оценить реальную полезность кандидата, а не просто уровень его теоретических познаний. Так как по любой интересующей теме можно сформулировать практическую задачу.
Вопросы
Приведу пример вопросов, которые, на мой взгляд, лучше раскрывают букет навыков девелопера, чем просто в лоб: 'Как работает memory management в iOS?'. Важно не только с ходу решить задачу, но еще и уметь найти/придумать это решение, если не знаешь как делать.
- Как бы вы стали верстать такой экран? Какие узкие места тут есть и как бы вы их решали?
Входящая информация:
Есть объект Product, который состоит из некой общей информации, которая находится в шапке, и массива Parameters. Каждый параметр — это строковые поля name и value. Value — это самая обычная строка, где каждое значение отделено вертикальной чертой от другого. Например: «VM 505|BWM ZIGZAG 3|SOLID REKT 101». Каждое значение должно находиться на новой строке как в 'Спецификации OEM'.
Обратить внимание:
Разделяющая полоса между name и value доходит до первого слова. В случае, если полоска делается как обычная вью, а поле value как лейбл, то полоса будет заканчиваться у самого длинного слова, а не у первого.
Уровень: middle и выше.
Решение: вариантов масса. От использованиямагии кровиCoreText до вставить люлей дизайнеру, чтобы переделал. Дальше сами решайте какой образ мысли вам ближе. - Что произойдет после запуска приложения?
func application(_ application: UIApplication, didFinishLaunchingWithOptions...) -> Bool { DispatchQueue.global().async { Timer.scheduledTimer(timeInterval: 0.4, target: self, selector: #selector(self.tickTimer), userInfo: nil, repeats: true) } return true } func tickTimer() { print("Tick-Tack") }
Я обычно не сторонник задач в стиле: 'Какая проблема в коде на картинке?', но слишком уж часто всплывает непонимание принципов работы таймера и ранлупов, которые выливаются в крайне неприятные и трудноуловимые баги.
Вопрос можно переформулировать в задачу: 'Нужно сделать повторяемый таймер, который вызывается каждую минуту в бекграунде. Прицельная точность тиков не важна, достаточно некая периодичность. Как это сделать?'
Уровень: junior и выше.
- Поступила задача. Нужно написать приложение, цветовая гамма которого конфигурируется на сервере. То есть, приложение получает конфиг в котором содержится набор цветов, степень скругления иконок, и так далее. Как лучше сделать такое приложение? Что будем использовать? Какие будут ограничения у того или иного решения?
Уровень: junior/middle и выше.
Обратить внимание: не дай бог кандидат промолчит о UIAppearance. Просто сc***ми тряпками гнать такого, особенно, если это middle и далее. Здесь же можно спросить про базовые классы Obj-C в качестве небольшого отступления к теории.
Отмечу, что кандидату не обязательно в деталях повествовать о работе UIAppearance. Он мог ни разу не использовать его, но что это такое знать обязан.
- Как сделать так, чтобы приложение могло себя обновлять без участия AppStore? Добавлять новые экраны и логику к ним, например. Какие есть ограничения у такого решения? Какое лучше подойдет в том или ином случае? Когда может быть реальная необходимость в этом механизме?
Уровень: senior.
- Есть приложение с таблицей. В процессе скроллинга периодически наблюдаются легкие притормаживания. Тестировщики не выявили явной закономерности, но проблема регулярно встречается. То тут, то там происходит неприятный лаг. Как его поймать? На что обращать внимание?
Уровень: middle и выше.
- Вопрос по Realm. Есть приложение с тем же чатом(можно любой другой пример), где таблица имеет некие разделители в виде даты или любого другого варианта. Как наиболее производительно сделать разделение по секциям? Какие есть варианты?
Уровень: middle и выше.
- Вопрос по CoreData. Есть приложение с тем же чатом. Сообщения могут приходить из сокета в одном из фоновых потоков. Нужно, чтобы пришедшее сообщение добавлялось в таблицу. Как будем делать? Какие есть варианты? С какими сложностями можно столкнуться?
Уровень: junior/middle и выше.
- Есть экран, наполнение которого зависит от нескольких запросов к серверу. То есть, содержимое должно быть показано только когда все они выполнятся. Например, страничка вконтакте. Пока не загрузится инфа о пользователе, сообщения со стены, первый поток фоток, должен крутится прогресс индикатор. Как будем строить логику?
Уровень: junior и выше.
Обратить внимание: хочу особенно здесь акцентировать на необходимость понимания gcd групп и синхронизации задач в Operation Queue. Будет здорово, если кандидат еще расскажет в чем разница того или иного решения.
- Случилась проблема. К вам прибежал разработчик из соседней команды и просит о помощи: приложение стало вылетать в релизе, но при этом нормально работает в дебаге. Как будем ловить ошибку? Что это может быть?
Уровень: middle и выше.
Обратить внимание: важно, чтобы кандидат был нацелен на результат. На факт исправления проблемы, а не на поиск причины. Первым делом человек должен спросить: 'Окей, гугл, а что, собственно, поменялось с момента, когда еще ничего не крашилось?', а только потом начинать захватывающий процесс отладки.
Почему это так важно: есть люди процесса, а есть результата. Разработчики процесса просто тратят деньги компании, что особенно заметно при лове нетривиальных багов. Они(разработчики) будут получать удовольствие от собственной компетенции, выставляя море бряков, читая статьи о вылетах и ошибках компилятора, погружаясь в профайлер с головой на весь день, когда достаточно было всего-то убрать сомнительный кусок кода. Это не значит, что не надо пользоваться профайлером и бряками. Просто надо понимать цель ради чего это делается.
- В приложении есть некий модуль, который проводит большое количество операций в длинном цикле. В определенный момент происходит креш, приложение просто закрывается. Даже когда оставили всего один вывод строки, то проблема сохранилась. Приведен код для примера, в реальности операции гораздо сложнее и насыщеннее, вылет происходит быстрее:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { for index in 0...1000000 { let string = NSString(format: "test + %d", index) print(string) } return true }
Что это может быть? Как это вылечить?
Уровень: middle и выше.
Обратить внимание: понимание принципов управления памятью. Хотя бы в целом.
Я бы сказал, что ситуация из вопроса крайне редкая и задачу стоит использовать только для совсем уж распальцованных синьеров, всем остальным достаточно знать о наличии retain/release/retain count и retain circle. - Немного классики. Вы проводите Code Review подопечного джуна, который пишет класс календаря для вашего приложения, и обнаруживаете следующий кусок кода:
protocol CalendarDelegateProtocol { func didSelect(date: Date) } public class Calendar: UIView { var delegate: CalendarDelegateProtocol! ... func didReceiveTouchForDate(date: Date) { self.delegate.didSelect(date: date) print("Did touch: (date)") } }
didReceiveTouchForDate — внутренний метод календаря, который вызывается при нажатии на определенную дату. Все ли тут в порядке на ваш взгляд?
Обратить внимание: проблем много, можно к каждой строчке докапываться почти. Чем больше деталей заметит соискатель, тем лучше.
Уровень: junior и выше.
- Тестировщики обнаружили баг, что пуши в приложении приходят только на iOS 10, но не на iOS 9. Как будем исправлять? В чем может быть проблема?
Еще одна задачка из той же серии: пуши приходят при установке приложения напрямую на устройство, но не из Testflight/Crashlytics/HockeyApp. Как с этим жить?
Обратить внимание: если соискатель с ходу не может ответить в чем конкретно проблема, то можно дать ему ноут и предложить найти решение. Если на ноуте будет установлено сразу несколько браузеров, то замечательно. Поймете в какой поисковой системе человек предпочитает искать, на русском или английском, как формулирует запросы и так далее.
Уровень: middle и выше.
- Есть одномерный строковый массив, данные из которого выводятся в таблицу. При этом массив может меняться откуда-то извне. Как сделать так, чтобы данные в таблице обновлялись по мере изменения массива? Например, если объект добавился в массив, то в таблице должна появиться новая строка.
Уровень: junior и выше.
- Вы делаете экран авторизации для Skype в storyboard с использованием autolayout. Так получилось. Все просто — квадратный лого, под ним текстовое поле и кнопка.
Вы классный, все сделали, но тут дизайнер заявляет, что при ландшафтной ориентации лого должно быть справа, а не сверху. Как будем делать?
Уровень: junior и выше.
- Нужно сделать scrollView с двумя картинками определенного размера друг под другом и отступами от края экрана со всех сторон в 30px. Нарисуйте на листочке какие будут констрейны.
Обратить внимание: понимает ли кандидат как определяется content size для scrollView? А если помнит про инсеты, так вообще замечательно. Может быть предложит поставить контент скроллвью на весь ее размер, без отступов, а расстояние от краев экрана сделать через margins.
Уровень: junior и выше.
Вопросы приведены в качестве примера. Если будет интересно, то составлю еще.
Мой посыл следующий — используйте практические задачи. Если не нашли подходящей, то составляйте их сами. Вы берете на работу не энциклопедию, а специалиста, который должен делать дело, а не просто знать все на свете. А уж тем более не держать в голове то, что можно найти в гугле за секунды. Главное, понимать что искать.
Как говорил господин Шерлок Холмс, на моем чердаке должны находиться только необходимые инструменты.
Незаметное зло
Но сомнительные вопросы — не единственная проблема. Есть еще один фактор, который может отпугнуть даже успешного кандидата. Это неуважительное, надменное или высокомерное отношение. И я говорю не о девочках-hr или важных руководителях. А о будущих коллегах.
Во многих местах, где я проходил собеседование, техническое интервью происходит без присутствия наблюдателя из hr или руководства. Что в целом естественно, зачем человеку, который ни слова не понимает в терминологии, терять час на занудную беседу в стиле вопрос-ответ?
А вот зачем. Многие разработчики воспринимают проведение собеседования как возможность самоутвердиться. И проверка знаний превращается в самое обыкновенное чудо унижение кандидата, добавляя бедняге стресса, независимо от квалификации. Даже если он успешно отвечает на любые вопросы. Подобное поведение я много где видел, как у своих коллег, так и на собеседованиях, где я был в роли интервьюимого.
На тему задранных носов есть замечательная картинка у xkcd:
Но это все вовсе не значит, что в разработку идут одни чудаки. Технических специалистов просто никто не учит вести переговоры, проводить интервью и строить уважительный диалог. И не редко встречаются люди просто замкнутые, а порой даже забитые. Руководство бросает их на амбразуры со словами: 'Проверь уровень этого парня, подойдет он нам или нет'.
При этом нет никаких стандартов, образцов и требований. Каждый проводит собеседование в меру своего понимания и мироощущения при полном отсутствии обратной связи. Ведь кто может дать эту обратную связь? Руководство/HR и кандидаты. Первые в процессе не участвуют и ничего не могут сказать, а кандидатам точно уж не до этого. Если их приняли, то значит все хорошо. Если же нет, то смысл дальше разговаривать?
Всем этим я хочу сказать как компаниям, так и каждому коллеге-разработчику в отдельности: обратите внимание не только на то как вы проводите интервью, но и манеру в которой общаетесь со своими подчиненными и коллегами. Канцерогенное отношение может проявляться не только к соискателям.
Попросите кого-то поприсутствовать на паре собеседований и дать вам обратную связь. Спросите у самих кандидатов впоследствии как все прошло, было ли некомфортно или еще что. Это как Code Review, ничего постыдного тут нет. Вы только станете лучше как специалист.
Уважительное общение должно являться стандартом в технической сфере.
Заключение
Если эта статья изменит ситуацию хотя бы в одной компании, то значит мои усилия были не напрасны.
Я постарался подобрать максимально полезные вопросы. Если есть потребность в дальнейшем пополнении списка, то в следующий раз посвящу этому отдельную публикацию.
Будет здорово, если поделитесь своими вопросами и заданиями, которые даете на собеседовании, чтобы проверить специалистов. Ведь кому-то достаточно пяти минут, чтобы понять уровень, а кто-то маринует по полтора часа каждого.
И, как говорится, уважайте друг друга. Независимо от глубины ваших познаний в материале — это не повод смотреть сверху вниз на окружающих. Аминь.
Автор: Mehdzor