Питання на співбесіді з розбору рішень з відповідями
Реальні сценарії з обмеженнями й трьома робочими варіантами: кешування, стилі API, рендеринг, відмовостійкість, зберігання даних, спостережуваність і релізи. Кожен розбір пояснює, коли підійшли б інші варіанти.
40 запитань для співбесіди з теми Розбір рішень з відповідями й поясненнями - рівні Junior, Middle і Senior. Приклади запитань, онлайн-тести й задачі на код.
- Компроміси
- Кешування
- API
- Відмовостійкість
- Спостережуваність
Запитання за рівнями
Junior
Базові поняття та синтаксис · 12 запитань
Middle
Практика, нюанси й оптимізація · 14 запитань
Senior
Архітектура, внутрішня будова, edge cases · 14 запитань
Приклади запитань
Кілька запитань із кожного рівня з правильною відповіддю й поясненням.
Розбір рішень · Junior
- Сайт із серверним рендером дає гостям вибрати темну тему. Перший же HTML має бути в правильній темі, без блимання. Де зберігати вибір?
Показати відповідь
Правильна відповідь: У cookie, яку сервер читає на кожен запит
Лише cookie доходить до сервера разом із запитом, тож HTML одразу рендериться в правильній темі.
localStorageпідходить для суто клієнтських застосунків або коли малий inline-скрипт може задати тему до малювання. Таблиця в базі підходить для автентифікованих користувачів, яким налаштування потрібне на всіх пристроях, але гості не мають акаунта. - Поле пошуку викликає API, де платять за кожен запит. Результати мають з'являтися під час введення, але не на кожну літеру. Що підходить?
Показати відповідь
Правильна відповідь: Debounce: запит після короткої паузи у введенні
Debounce надсилає один запит, коли введення зупинилося, тож серія натискань коштує одного виклику, а результати з'являються без додаткових дій. Throttle підходить для безперервних потоків, як прокрутка чи зміна розміру, де важливі регулярні оновлення, але тут ви платили б за недописані слова. Пошук за Enter найдешевший і підходить для дорогих пошуків, але порушує вимогу показувати результати під час введення.
- Статті популярного блогу редагують кілька разів на день. Важливий пошуковий трафік, а текст давністю до години прийнятний. Як рендерити сторінки?
Показати відповідь
Правильна відповідь: Попередньо рендерити й оновлювати щогодини
Попередній рендер із періодичним оновленням віддає читачам і пошуковим роботам швидкий кешований HTML, а година застарівання тут дозволена. Рендер на кожен запит підходить для персоналізованих сторінок чи даних, що мають бути актуальними при кожному візиті, а тут він лише додав би навантаження. Клієнтський рендер підходить для приватних панелей, але сповільнює перше малювання й погано пасує сторінкам, що залежать від пошуку.
- Каталог онлайн-магазину має 10 000 товарів. Покупці порівнюють товари, діляться посиланням на позицію й потребують футера. Як показувати список?
Показати відповідь
Правильна відповідь: Нумеровані сторінки з номером у URL
Нумеровані сторінки дають кожній позиції URL, яким можна поділитися, і лишають футер досяжним, а саме це потрібно каталогу. Нескінченна прокрутка підходить для стрічок, які гортають без мети, де позиція неважлива. Віртуалізований список підходить для інструментів із великими даними, де всі рядки потрібні на клієнті, але завантажувати весь каталог тут марнотратно.
Розбір рішень · Middle
- Стрічка новин обслуговує 1 млн користувачів, може відставати на хвилину, а кожен виклик зовнішнього API платний. Який головний підхід?
Показати відповідь
Правильна відповідь: Спільний серверний кеш із TTL близько 60 секунд
Один спільний запис означає, що всі користувачі коштують одного виклику на хвилину, а хвилина відставання дозволена. Кеш у браузері підходить для особистих даних і економить повторні візити, але за 1 млн користувачів кожен усе одно коштує виклику. Запит при кожному візиті підходить для даних, що мають бути точними, як баланс, а тут лише примножив би рахунок.
- Після переказу користувач відкриває баланс. Сума має бути точною, а решта банківського застосунку читає з реплік. Куди йде це читання?
Показати відповідь
Правильна відповідь: На primary, без кешу між ними
Гроші, показані одразу після запису, мають відображати цей запис, і це гарантує лише primary. Репліка підходить для списків та історії, де секунда відставання нешкідлива. Кеш з інвалідацією підходить для даних, що часто читаються й рідко пишуться, але пропущена інвалідація тут покаже неправильний баланс, а це дорожче за зайве читання.
- Ви публікуєте API для зовнішніх партнерів, що пишуть багатьма мовами. Відповіді мають працювати із CDN, а перший виклик партнера має займати хвилини. Який стиль?
Показати відповідь
Правильна відповідь: REST через HTTP з описом OpenAPI
REST не потребує нічого, крім HTTP-клієнта, а відповіді GET одразу працюють із CDN. GraphQL підходить клієнтам із дуже різними потребами в даних, хоча кешування зазвичай вимагає більше роботи, бо запити часто йдуть через POST. gRPC підходить для швидких внутрішніх викликів між вашими сервісами, але потребує згенерованих клієнтів і не працює напряму з браузера.
- Вебу й мобільному застосунку потрібні дуже різні дані з тих самих сервісів. Кожен клієнт має власну команду, а мобільний страждає від великих відповідей. Що додати?
Показати відповідь
Правильна відповідь: Окремий BFF у кожної клієнтської команди
BFF дає кожній команді формувати відповіді під свої екрани й випускати їх без очікування інших. Параметр
?fields=підходить для малих відмінностей в одному ресурсі, але не агрегує кілька сервісів для екрана. Прямі виклики підходять для дуже малої системи, а тут додадуть мережевих обмінів на мобільному й розкриють внутрішню будову сервісів.
Розбір рішень · Senior
- Соцмережа обслуговує переважно користувачів із кількома сотнями підписників, а також акаунти з 50 млн. Читання має бути швидким. Як будувати стрічки?
Показати відповідь
Правильна відповідь: Гібрид: fan-out при записі, крім величезних акаунтів
Заздалегідь зібрані стрічки роблять читання швидким для більшості акаунтів, а додавання величезних акаунтів при читанні уникає мільйонів записів на пост. Чистий fan-out при записі підходить для мережі без екстремальних акаунтів, але один пост знаменитості залив би шлях запису. Чистий fan-out при читанні підходить системам із малим читанням і лишається простим, але в такому масштабі збирання кожної стрічки надто повільне.
- Магазин віддає сторінки товарів із глобального CDN. Описи змінюються рідко, але виправлена ціна має з'явитися за секунди. Яка стратегія кешування?
Показати відповідь
Правильна відповідь: Довгий TTL у CDN плюс очищення за тегами при зміні
Довгий TTL тримає високу частку влучань, а очищення за тегом за секунди застосовує виправлену ціну всюди. Короткий TTL підходить для вмісту, де немає подій зміни, але він спрямовує на джерело значно більше трафіку. Відмова від CDN підходить для повністю персоналізованих сторінок, а тут вона позбавила б швидкості відвідувачів з усього світу.
- Стартап із шести людей ще шукає відповідність продукту ринку, а межі домену постійно зсуваються. З якої архітектури почати?
Показати відповідь
Правильна відповідь: Модульний моноліт із чіткими внутрішніми межами
Модульний моноліт лишає рефакторинг дешевим, поки межі зсуваються, а чисті модулі згодом можуть стати сервісами. Мікросервіси підходять багатьом командам, яким потрібні незалежні релізи, а шестеро людей витрачали б час на мережу й деплой. Функції на ендпоінт підходять для пікових ізольованих навантажень, а розкидання мінливого домену по них ускладнює розвиток спільної логіки.
- Після збереження замовлення сервіс має опублікувати подію в брокер. Події не можна втрачати, а брокер не бере участі в транзакції бази. Що зробити?
Показати відповідь
Правильна відповідь: Transactional outbox із публікацією через relay
Запис події в одній транзакції із замовленням означає, що існують обидва або жодне, а relay доставить подію згодом. Публікація після коміту підходить для подій, які можна втратити, але збій між двома кроками її губить. Публікація першою не підходить ні до чого, що має бути узгодженим, бо невдалий коміт лишає споживачів із реакцією на неіснуюче замовлення.
Задачі на код
Напишіть рішення просто в браузері - тести перевірять його одразу. Класика співбесід на JavaScript (debounce, deepClone, Promise.all, LRU-кеш), на TypeScript (дженерики, звуження й утилітні типи, перевіряє справжній компілятор), серверна логіка на Node.js (middleware, обмеження частоти, черги задач), SQL-запити в справжньому PostgreSQL і на React: компоненти й хуки на кшталт списку справ, вкладок, useDebounce та useInterval.
Відкрити задачі →