Профессионально заниматься программированием я начал шесть лет назад, успел поработать со многими технологиями, создавая мобильные приложения и бэкенд-сервисы. Я неплохо разбираюсь в микросервисах и архитектуре, ориентированной на события. Мои рабочие обязанности состояли в том, чтобы устранять проблемы через код, ну и ходить на собрания иногда.
Несколько месяцев назад я решил устроиться на должность программиста-сениора: внес в резюме все самые свежие свои навыки и проекты и разослал его по компаниям. Одна из этих компаний пригласила меня на серию собеседований стандартного типа: одна встреча посвящена написанию кода, другая – проектированию систем, еще несколько – соответствию командной культуре и завершает всё финальная встреча с руководителем или замом команды программистов. Все этапы прошли хорошо, за исключением того, который касался проектирования систем. О нём я и хотел бы вам рассказать.
Я вкратце изложу, что происходило на собеседованиях, ориентированных на код и командную культуру, хотя ничего выдающегося там не было – эту пару абзацев можете пропустить. С написанием кода никаких сложностей не возникло, я выполнил задачу и уложился в предоставленное время, правда, не учел некоторые пограничные случаи. Я их проговорил и наметил возможные решения, но вот расписать в коде уже не успел. Сотрудников, проводящих собеседование, это устроило, и первый этап мне зачли.
Затем последовало знакомство с культурой команды – это было довольно весело и связанные с программированием темы практически не поднимались. В основном мы обсуждали рабочие процессы, я высказывал свои мнения о том, как должно быть организовано тестирование, командная работа, обсуждения и так далее. В общем, просто поговорили. Еще одна встреча прошла в похожем ключе, там я рассказывал о том, почему хочу попасть в компанию, и о своем предыдущем опыте в сфере IT – тоже ничего сложного.
Наконец, мы переходим к собеседованию, посвященному проектированию систем, и тут всё становится интереснее – в смысле, я его завалил. Постараюсь углубиться в детали того, как оно проходило, объяснить, где и что я сделал не так, и дать некоторые рекомендации.
Моей задачей на этом собеседовании было спроектировать сервис для сокращения ссылок.
Функциональные требования приводились следующие:
- Сервис должен генерировать для загруженного адреса короткую версию, в которой за доменным именем следует ключ длиной в семь символов. Это называется короткой ссылкой: например, shorturl.com/9zck6rc.
- Когда пользователь пытается перейти по короткой ссылке, сервис должен перенаправить его на исходный адрес.
Нефункциональные требования были такими:
- У системы не должно быть никаких проблем с доступом, иначе перенаправление по ссылкам начнет давать сбои.
- У двух разных адресов не может быть одинаковых коротких ссылок.
- Предположительное количество пользователей составляет около тысячи в день.
Для начала я определился с тем, какие конечные точки нам понадобятся, чтобы создавать короткие ссылки и как мы будем извлекать ссылки исходные. Получался простой сервис с базой данных, где будут храниться все id, long_url, short_url, и created_at. По ходу дела у нас с собеседующим состоялось обсуждение нескольких вопросов.
Вопрос первый: SQL или NoSQL
Я начал с того, что выбрал подходящий тип базы данных для сервиса. Я предложил NoSQL – совсем вылетело из головы, что, раз объем аудитории у нас небольшой, о масштабировании можно не беспокоиться. Аргументы в пользу NoSQL я приводил довольно убедительные, но для нужд инструмента, который мы проектировали, вполне хватило бы и SQL – обосновать, почему выбор должен непременно пасть именно на систему NoSQL, мне не удалось. Я стал приводить примеры сервисов, которые используют NoSQL, типа систем бронирования, и оседлал этот конёк надолго.
Ошибка первая: Я увлекся объяснениями. Да, нужно пояснять для того, кто проводит собеседование, почему вы выбираете именно такой вариант, но слишком долго излагать лишние подробности всё-таки ни к чему. Я несколько минут проговорил о том, что в реальности можно было бы объяснить в нескольких фразах. Очень важно уметь себя остановить, чтобы не продолжать развивать мысль до бесконечности.
Рекомендация: вызывайте собеседника на обратную связь. Диалог не должен превращаться в монолог.
Вопрос второй: генерация короткой ссылки
Дальше следовал ключевой для работы системы шаг: нужно было задать логику, по которой будут генерироваться короткие ссылки. Не буду слишком грузить подробностями, но там нужно было вычислить уникальный хэш (SHA256), а затем закодировать его в Base62. У этого способа имеются определенные недостатки, есть риск, что появятся дубликаты.
Я не сумел найти решение, чтобы генерировать ровно семь символов и при этом разбираться с дубликатами в процессе хэширования. Близко подошел к правильному ответу, но не смог разрешить возникшие проблемы.
Ошибка вторая: у меня были ложные ожидания. Я не предполагал, что на собеседовании по проектированию систем будут до такой степени уходить в детали. К моему большому удивлению, расспрашивали очень подробно. Более того, с точки зрения собеседующего, именно это и составляло основную суть задачи, здесь я и должен был показать свои знания. Мне следовало уделить этому вопросу больше времени, а я вместо этого потратил непозволительно много на предыдущую тему.
Рекомендация: попытайтесь расставить подзадачи в порядке приоритета – можно уточнить у собеседующего, верны ли ваши предположения. Так вы будете двигаться в правильном направлении и с пониманием, на каких моментах нужно максимально сосредоточиться.
Вопрос третий: репликация базы данных
Проговорив вычислительную логику, я стал намечать архитектуру для принятия запросов и сохранения поступающих данных. Рассуждая о масштабировании, я мимоходом заметил, что можно было бы проводить репликацию базы данных. После этого разговор перешел на репликацию баз данных и механизмы репликации вообще. Я что-то там сказал про синхронную и асинхронную репликацию, однако сам я подобными вещами никогда не занимался, поэтому ответ прозвучал туманно и шаблонно.
Ошибка третья: мне не хватило духу сказать: «Не знаю». Если в чем-то разбираешься плохо, лучше просто это признать. На собеседованиях по проектированию систем у меня такое случалось неоднократно: задают вопрос, ответа не знаю, прекрасно понимаю, что не придумаю ничего толкового, но всё равно упорно продолжаю попытки что-то выдумать.
В таких случаях самое разумное – определить, насколько большой вес обсуждаемая проблема имеет в контексте задания, и вести разговор сообразно с этим. В моём случае без репликации базы данных вообще можно было прекрасно обойтись, пользователей-то кот наплакал.
Рекомендация: не бойтесь сказать: «Не знаю», если это сбережёт вам время на более важные вещи.
Вопрос четвёртый: кэширование
Сервис должен был работать с низкой задержкой. Причины лежали на поверхности: в обратном случае пользователю пришлось бы подолгу ждать, чтобы банально открыть сайт. Решение тоже напрашивалось само собой – кэширование адресов самых посещаемых сайтов.
Следующий вопрос касался того, как определять самые посещаемые адреса. Я предложил кэшировать каждый адрес, который еще не записан в системе, а затем уже удалять те, которые совсем не используются. Для нашей системы исходить из того, какие адреса посещаются реже всего, представлялось разумной политикой.
Затем меня спросили, как насчет репликации кэша, на случай если загружать сайты будут из разных регионов. Я предложил использовать репликацию баз данных и с опорой на это проводить инвалидацию кэша, но застрял на деталях.
Ошибка четвертая: мне не хватило уверенности. С концептом распределенного кэширования я знаком хорошо, даже в проектах применял его не раз, но отвечая на этот вопрос, почему-то усомнился в своих знаниях. Хотя решение было рабочее, мне показалось, что меня куда-то не туда понесло. А ведь единственное, что здесь надо было добавить – это упомянуть издержки такого подхода.
Рекомендация: здесь можно только пожелать всем верить в себя. Если в чем-то разбираетесь — значит разбираетесь.
Надеюсь, вы что-то для себя извлекли из моего полуторачасового невесёлого опыта. Собеседование было для меня по-своему увлекательным – оно указало на многие пробелы в моих знаниях. Выводы, которые для себя сделал, помогли мне правильно распределять внимание в дальнейшем, благодаря чему следующие несколько собеседований прошли успешно.
ссылка на оригинал статьи https://habr.com/ru/company/productivity_inside/blog/555276/
Добавить комментарий