Мой 45-минутный опыт интервью по дизайну продукта
7 ноября 2022 г.Введение
Я хотел бы поделиться своим опытом прохождения 45-минутного собеседования по дизайну продукта (НЕ собеседования по системному дизайну) в технологической компании. Все, что описано ниже, является моим опытом, это НЕ эталонный ответ и не претендует на таковое.
Задача
Вам необходимо разработать API для реализации ленты новостей, как показано на следующем рисунке.
Решение
Понимание задачи
Как обычно, само задание очень высокого уровня и неясно, и наша первая цель — задать как можно больше важных вопросов, чтобы понять контекст задания. Давайте зададим первую часть вопросов:
- Существуют ли ограничения на использование типов API? Это позволяет нам избавиться от первого решения, какой API мы должны использовать: REST, веб-сокет, GraphQL и т. д., или, по крайней мере, показать интервьюеру, что нам это небезразлично.
- Сколько у нас пользователей и какова ожидаемая нагрузка? Это один из основных факторов, влияющих на все решения во время собеседования, и лучше сразу понять это требование, чтобы сэкономить время.
- Сколько типов клиентов (iPhone, Android, ПК и т. д.) ожидается? Будет ли отличаться дизайн? Если тип клиента только один, или хотя бы дизайн одинаковый для всех клиентов, это позволит сделать только одну версию API, иначе придется решать дополнительную задачу.
Конечно, мы можем задать гораздо больше вопросов, но мы должны помнить, что время ограничено, и нам нужно получить только самую важную информацию для принятия решений.
Первые шаги
Основываясь на ответах выше, мы решили приступить к разработке необходимого API. Давайте представим, что нам нужно использовать REST API. Итак, нам нужна хотя бы одна конечная точка, чтобы получить список последних сообщений:
Конечная точка
ПОЛУЧИТЬ /posts
Запрос
{
"count": 2
}
Ответ
{
"posts": [
{
"picture_url": "",
"text": "",
"comments_ammount": 42,
"likes_amount": 146
},
{
"picture_url": "",
"text": "",
"comments_ammount": 22,
"likes_amount": 246
}
]
}
Эта конечная точка позволяет нам отображать именно тот макет, который нам нужен, но имеет несколько проблем:
- Как мы собираемся загружать следующие сообщения во время прокрутки? Если мы собираемся сделать еще один запрос, мы можем получить те же сообщения.
- Как мы будем сортировать сообщения? Что, если возвращаемые сообщения будут самыми старыми, а нам нужны самые новые?
- Как мы можем получить точные комментарии или список людей, которым понравился пост?
Это не исчерпывающий список проблем, но, на мой взгляд, они наиболее критичны, поэтому давайте попробуем их исправить.
Улучшения
Итак, как мы можем решить проблему №1? Здесь я вижу два пути:
- Просто, но ограничено. Загрузите максимальное количество сообщений, скажем, 1000, и разрешите пользователям прокручивать ленту только до этого количества.
- Используйте нумерацию страниц и получайте сообщения партиями.
Это сложно даже назвать компромиссом, так как выбор очевиден. Лучший вариант — использовать пагинацию, она позволяет нам получать посты пропорционально.
Запрос
{
"offset": 0,
"limit": 2
}
Ответ
{
"offset": 0,
"limit": 2,
"posts": [
{
"picture_url": "",
"text": "",
"comments_ammount": 42,
"likes_amount": 146
},
{
"picture_url": "",
"text": "",
"comments_ammount": 22,
"likes_amount": 246
}
]
}
Теперь мы можем получать сообщения по пакетам, что помогает нам избежать повторного рендеринга одного и того же сообщения.
Чтобы решить проблему №2, нам нужно добавить больше полей, чтобы иметь возможность сортировать наши сообщения. Здесь у нас есть как минимум 2 способа:
- Более гибкий. Мы можем получить два поля:
как
сортировать ичто
сортировать. Например, отсортируйте в порядкевозрастания
по полюcomments_ammount
. Это делает наше решение гибким, но увеличивает сложность. - Более просто. Если мы говорим о новостных лентах, то в большинстве случаев пользователи хотят сортировать посты только по дате. Таким образом, у нас может быть только одно поле:
как
сортировать. Например, отсортируйте в порядкевозрастания
— самые старые сообщения будут первыми.
Я бы сейчас выбрал более простой вариант, в любом случае его можно улучшить позже.
Запрос
{
"offset": 0,
"limit": 2,
"sort": "ASCENDING"
}
Ответ
{
"offset": 0,
"limit": 2,
"posts": [
{
"picture_url": "",
"text": "",
"comments_ammount": 42,
"likes_amount": 146,
"date": "2022-09-08T09:45:55Z"
},
{
"picture_url": "",
"text": "",
"comments_ammount": 22,
"likes_amount": 246,
"date": "2022-09-10T09:45:55Z"
}
]
}
Перейдем к проблеме №3 — как посмотреть комментарии и лайки. Опять же, у нас есть несколько способов решить эту проблему:
- Реализуйте отдельную конечную точку, чтобы получать все комментарии/лайки для сообщений по
post_id
. Этот подход будет иметь лучшую производительность для загрузки фида, так как мы получим меньше данных. Но это заставляет пользователей ждать, когда они захотят увидеть комментарии. - Добавьте комментарии/лайки в ответ фида. Этот подход противоположен предыдущему. Это замедлит загрузку фида, но ускорит просмотр комментариев/лайков.
- Гибридный подход. Включите N лучших комментариев/лайков в ответ фида и реализуйте отдельные конечные точки для получения полных данных. Этот самый сложный, но и самый оптимальный.
Гибридный подход выглядит здесь наиболее подходящим, и он не требует больших усилий, поэтому воспользуемся им.
Конечная точка
ПОЛУЧИТЬ /posts
Запрос
{
"offset": 0,
"limit": 2,
"sort": "ASCENDING"
}
Ответ
{
"offset": 0,
"limit": 2,
"posts": [
{
"id": 12345,
"picture_url": "",
"text": "",
"comments_ammount": 42,
"likes_amount": 146,
"date": "2022-09-08T09:45:55Z",
"top_comments": [
{
"id": 1,
"author_id": 2,
"text": ""
},
{
"id": 2,
"author_id": 4,
"text": ""
}
],
"top_likes": [
{
"id": 1,
"author_id": 5
},
{
"id": 2,
"author_id": 8
}
]
},
{
"id": 12346,
"picture_url": "",
"text": "",
"comments_ammount": 22,
"likes_amount": 246,
"date": "2022-09-10T09:45:55Z",
"top_comments": [
{
"id": 4,
"author_id": 10,
"text": ""
},
{
"id": 5,
"author_id": 11,
"text": ""
}
],
"top_likes": [
{
"id": 6,
"author_id": 12
},
{
"id": 7,
"author_id": 16
}
]
}
]
}
Конечная точка
ПОЛУЧИТЬ /posts/{id}/comments
Запрос
{
"offset": 0,
"limit": 4,
"sort": "ASCENDING"
}
Ответ
{
"offset": 0,
"limit": 4,
"comments": [
{
"id": 4,
"author_id": 10,
"text": ""
},
{
"id": 5,
"author_id": 11,
"text": ""
},
{
"id": 6,
"author_id": 10,
"text": ""
},
{
"id": 7,
"author_id": 11,
"text": ""
}
]
}
Конечная точка для лайков выглядит так же, поэтому мы опускаем ее здесь.
Время истекло
Вполне вероятно, что к этому моменту 45-минутное интервью подошло к концу, и стоит окончательно принять решение. Мы, безусловно, подготовили работающий API, но проблем еще много, и стоит их быстро проработать.
- Что делать, если во время прокрутки будут создаваться новые сообщения? Это означает, что
offset
будет сдвинут и при следующем запросе мы получим дублированный пост. - Как насчет скорости загрузки изображений? Должны ли мы добавить несколько вариантов URL-адреса изображений:
preview
— маленький, но низкого качества иfullsize
— большой с хорошим качеством? - Что делать с загрузкой новых сообщений? Должны ли мы использовать длинный пул или модель публикации/подписки?
Заключение
Обратите внимание, что существует несколько вариантов решения проблемы (компромиссов), ваша задача как кандидата состоит в том, чтобы показать, что вы их видите, и попытаться обосновать свой выбор наилучшего варианта. И не переживайте, если после собеседования вы поймете, что что-то упускаете. Цель интервью — увидеть, как вы думаете, а не подготовить реальный дизайн продукта.
Также опубликовано здесь
Оригинал