Собеседования не очень приятный опыт, чаще всего. На первое собеседование идти страшно. В дальнейшем — нервно, сложно и опять-таки страшно. Если действительно хочется получить работу в этой компании.



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


В первую очередь стоит быть в курсе, что требуется в индустрии. Вот прямо сейчас. Какого специалиста не хватает компании для какой — либо задачи. Оставим обиды на рекрутеров, которые ставят абстрактные требования к кандидату, в стороне. Я говорю о настоящем собеседовании, когда кандидат общается с потенциальным начальником или коллегами, чтобы определить, подходят ли они друг другу. Что компания хотела бы, чтобы вы умели? Какой стек технологий сейчас популярен? Каков уровень специалистов, которые уже есть в компании?


Мой пример — собеседование с программистами из Яндекс.Такси для Flutter-разработчика. Примерные вопросы, которые я приведу, могут помочь при подготовке к собеседованию.


  • Основы языка. Пожалуй меня спросили обо всех системных словах, которые используются в языке и хоть немного отличаются от всех остальных языков. Future, stream, generic, abstract, static, final, const, mixin, в чем отличие stateless и stateful виджетов. В общем нужно знать ответы на вопросы, о которых программист чаще всего или не задумывается, потому что это выведено на уровень автоматизма, или не использует, потому что у него другой стиль написания программ. Думает ли программист, почему в общепринятом шаблоне начального приложения точка входа в программу задается как main? Мне кажется нет. Это очевидно. Он хочет написать новую программу, создает новый проект и открывает main. А почему? Как объяснить очевидное? (хотя конкретно в Dart это просто функция верхнего уровня и она не обязана называться main, можно назвать ее как угодно, это просто точка входа в программу, которая задана в конфигурации. Более того, можно иметь даже несколько таких точек входа, то есть разные конфигурации запуска приложения). Вот также произошло и со многими вопросами, заданными мне моими собеседниками. Как объяснить им то, что я делаю ежедневно на уровне автоматизма? Как рассказать им, что для меня future и stream — это не определения из учебника, а что-то на уровне чувств, о чем не надо сознательно задумываться? И вот эти вопросы, ответы на которые, казалось бы, очевидны, стали для меня основой переосмысления технологии и дальнейших исследований архитектур приложения, доступных на Flutter.
  • Hot reload. Простейшая, казалось бы, вещь, которой я не пользовалась. В Android studio при работе с Flutter проектами есть несколько режимов обновления приложения на тестовом устройстве после внесения изменений. На кнопках в панели инструментов есть play с точкой. Эта команда перезапустит приложение с начального экрана, но не будет перестраивать его целиком. Если внесены изменения в список библиотек, эта кнопка бесполезна, нужно перестроить приложение заново. Есть и ещё один способ обновления: нажать ctrl+s. Сохранение. Этот способ оставит приложение на том же самом экране, где находился пользователь во время обновления. Этот вариант идеален для просмотра визуальных изменений. А вот если виджет поменялся и вместо stateless стал stateful, это приведёт к ошибкам (красному экрану), которых не будет после перезапуска приложения. В общем, более-менее ощутимые изменения кода в этом режиме приведут к непредсказуемому результату, когда программист не сможет с уверенностью сказать, вызвана ошибка hot reload или сам код ошибочен. В общем, я почти не жалею, что до интервью не задумывалась об этом способе обновления при просмотре. Хотя менять дизайн действительно проще именно так.
  • Паттерны разработки мобильных приложений. MVC (model-view-controller) — паттерн, которому уже больше 30 лет. Кроме него, часто говорят об mvp, mvvm, и все они настолько похожи по своему принципу друг на друга, что часто не хочется задумываться, в чем же разница, потому что общее у них — цель применения: мы хотим разделить внешний вид и бизнес логику для удобства тестирования, чтения кода и его дальнейшей модификации. В этом смысле все они одинаковы. И именно собеседование заставило меня копнуть глубже и посмотреть, какие архитектуры рекомендуются сейчас и как другие люди строят свои приложения. Сразу скажу, что на момент моего изучения флаттера не было столь хорошей проработки паттернов, как есть сейчас, например, здесь. А после того, как я уже начала успешно писать приложения, причины копаться в деталях реализации не было. С помощью stream и future можно написать классное приложение, юнит-тестировать его и не знать никаких проблем с реализацией. И скорее всего в результате такой работы получится вполне приличное приложение с архитектурой MVVM (если попытаться его классифицировать). Я бы например не стала искать что-то новое, если все и так работает. Тем не менее для флаттера сейчас популярен BLOC. Термин этот я не встречала в андроид натив или где-то еще. BLOC хорош тем, что это и Dependency Injection, и контроль состояния, и упрощение кода. Все в одном и предельно просто для начинающих. По примеру (которых достаточно много), можно легко написать свой вариант простого приложения, который будет при этом использовать такие непонятные для начинающего вещи как асинхронные генераторы (и при этом вы вряд ли задумаетесь, что это действительно такое). Мне лично BLOC нравится своей описательностью. Задача программиста: последовательно описать три файла — state — все состояния экрана (функции), event — события, которые происходят на этом экране и могут привести к изменению состояния и наконец bloc — правила, по которым происходят изменения. Когда все это описано, места для ошибок практически не остается. С другой стороны, это не очень гибкий вариант описания происходящего на экране.
  • Generic типы данных. Позволяют применять одни и те же методы/объекты/функции к разным типам данных. Предположим, имеется маркированный список, который будет использоваться для разных типов данных — строк, чисел, объектов. На экране каждый такой объект может быть представлен текстом, полученным с помощью метода toString(), но выбранное значение необходимо сохранить именно в том типе данных, который был получен, а не в строке. Здесь и будет полезно задать generic тип для виджета элемента списка. Пример кажется надуманным, но мы встречаемся с generic типами очень часто, например, каждый раз, когда описываем класс State для Stateful виджета. State<WidgetName> — это тоже использование generic, хотя об этом тоже вряд ли кто-то задумывается, когда пишет это.
  • Typedef — способ дать имя какому-то конкретному типу функций, для них заданы типы и количество параметров и тип результата. В качестве примера использования можно представить виджет, который в результате взаимодействия с пользователем должен выполнить функцию с набором параметров, которые были выбраны пользователем. В конструктор такого виджета можно передать как раз такую функцию, тип которой задан через typedef.


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


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


Проходите собеседования, получайте от этого удовольствие и новые знания. Оно стоит того.