Пошук уроків, статей та іншого контенту
Освоїте техніку уточнювальних запитань для виявлення сценаріїв користувачів, пріоритетів і меж системи.
У системному дизайні недостатньо отримати запит на кшталт:
«Потрібно додати сповіщення користувачам».
Це лише загальний опис ідеї. За ним незрозуміло:
хто саме отримує сповіщення;
які події їх запускають;
через які канали вони надсилаються;
наскільки швидко вони мають доставлятися;
що робити у випадку помилки;
які обмеження має система;
що є обов’язковим, а що можна реалізувати пізніше.
Уточнювальні запитання допомагають перетворити нечіткий запит на набір конкретних вимог. Лише після цього можна обґрунтовано проєктувати компоненти системи.
Зручно ставити запитання послідовно, переходячи від загальної мети до деталей.
Спочатку потрібно зрозуміти, яку проблему розв’язує система.
Корисні запитання:
Яку проблему ми намагаємося вирішити?
Хто є основним користувачем?
Який результат вважається успішним?
Чому ця функція потрібна саме зараз?
Як користувачі розв’язують цю проблему сьогодні?
«Користувач має дізнатися про зміну статусу замовлення протягом однієї хвилини, навіть якщо він не відкрив сайт».
Це вже дає важливий напрям для подальшого проєктування.
Потрібно з’ясувати, що саме робить користувач і як система реагує.
Запитання:
Хто ініціює дію?
Яка подія запускає процес?
Які кроки виконує користувач?
Який результат очікує користувач?
Що відбувається у разі помилки?
Чи є різні типи користувачів?
Чи відрізняються сценарії для вебверсії та мобільного застосунку?
Зручно описувати сценарій у такій формі:
Користувач виконує дію.
Система отримує або створює подію.
Система перевіряє умови.
Система виконує дію.
Користувач отримує результат.
Запит:
«Потрібно повідомляти користувача про нові замовлення».
Уточнений сценарій:
Продавець створює замовлення.
Система перевіряє, що замовлення успішно збережене.
Система надсилає покупцю push-сповіщення.
Якщо push недоступний, система надсилає email.
Усі спроби доставки записуються для подальшого перегляду.
Такий опис уже показує, які події, канали та помилки потрібно врахувати.
Відкриті запитання допомагають отримати контекст і не нав’язують відповідь.
Приклади:
Як користувачі мають взаємодіяти з цією функцією?
Що має відбутися після створення замовлення?
Які проблеми виникають у поточному процесі?
Що станеться, якщо зовнішній сервіс буде недоступний?
Після цього використовуйте закриті запитання, щоб перевірити конкретні припущення:
Чи потрібно надсилати сповіщення через email?
Чи може один користувач мати кілька пристроїв?
Чи потрібно повторювати невдалу спробу доставки?
Чи має сповіщення бути доставлене протягом однієї хвилини?
У вимогах часто зустрічаються слова, які різні люди розуміють по-різному:
«швидко»;
«багато користувачів»;
«надійно»;
«майже в реальному часі»;
«усі дані»;
«підтримати різні пристрої».
Необхідно замінювати їх вимірюваними умовами.
Замість:
«Система має швидко надсилати сповіщення».
Краще запитати:
«За який максимальний час після події сповіщення має бути доставлене у 95% випадків?»
Замість:
«Система має підтримувати багато користувачів».
Краще запитати:
«Скільки активних користувачів очікується зараз і скільки — через рік? Чи всі вони можуть виконувати дії одночасно?»
Не всі вимоги однаково важливі. Якщо цього не з’ясувати, команда може витратити час на другорядні можливості й не встигнути реалізувати основний сценарій.
Для кожної вимоги потрібно визначити її пріоритет:
обов’язкова — без неї система не розв’язує основну проблему;
важлива — значно покращує продукт, але може бути відкладена;
бажана — корисна додаткова можливість;
поза межами першої версії — не реалізується зараз.
Запитання для визначення пріоритетів:
Який сценарій є найважливішим?
Що має працювати в першій версії?
Яку функцію можна відкласти?
Що станеться, якщо ця вимога не буде реалізована?
Які компроміси прийнятні?
Що важливіше: швидкість, вартість, повнота функцій чи надійність?
Для системи сповіщень:
доставити повідомлення про зміну статусу замовлення — обов’язково;
підтримати push-сповіщення — обов’язково;
повторити доставку після тимчасової помилки — важливо;
дати користувачу змогу налаштовувати типи сповіщень — бажано;
додати SMS-сповіщення — поза межами першої версії.
Пріоритети потрібно погодити із замовником або власником продукту, а не визначати самостійно.
Межі системи показують, що саме ми проєктуємо, а що належить до інших компонентів або зовнішніх сервісів.
Потрібно з’ясувати:
Які функції входять до системи?
Які функції вже реалізовані в інших сервісах?
Які зовнішні системи потрібно викликати?
Хто відповідає за зберігання даних?
Чи має наша система змінювати зовнішні дані?
Які дані входять у систему і які виходять із неї?
Для сервісу сповіщень:
До системи входить:
отримання подій від сервісів замовлень;
вибір каналу доставки;
постановка повідомлення в чергу;
надсилання повідомлення;
запис результату доставки.
До системи не входить:
створення замовлення;
редагування профілю користувача;
реалізація мобільного push-провайдера;
текстова модерація повідомлень.
Це допомагає не розширювати задачу безконтрольно.
Вони описують, що має робити система.
Приклади:
приймати події про зміну статусу замовлення;
знаходити отримувача повідомлення;
надсилати повідомлення через вибраний канал;
повторювати доставку після тимчасової помилки;
зберігати статус спроби доставки.
Вони описують, як саме система має працювати.
Приклади:
95% повідомлень мають бути доставлені не довше ніж за одну хвилину;
система має обробляти 10 000 подій за хвилину;
повторне надсилання не має створювати дублікати;
помилки зовнішнього провайдера мають бути видимі операторам;
дані потрібно зберігати протягом 30 днів.
Для нефункціональних вимог особливо важливо уточнювати вимірювані значення.
Навіть на початку проєкту потрібно приблизно оцінити масштаб системи.
Запитання:
Скільки користувачів буде користуватися функцією?
Скільки подій виникає за секунду або хвилину?
Яке максимальне навантаження?
Чи бувають різкі піки?
Який обсяг даних потрібно зберігати?
Як швидко зростатиме цей обсяг?
Важливо розділяти:
середнє навантаження — звичайна кількість запитів;
пікове навантаження — максимальна кількість запитів за короткий період.
Наприклад, у середньому може виникати 100 подій за секунду, але під час розпродажу — 2000 подій за секунду. Для архітектури це різні вимоги.
На цьому етапі не обов’язково отримати ідеально точні числа. Потрібні хоча б приблизні оцінки та домовленість про те, які припущення використовуються.
Обмеження впливають на можливі рішення не менше, ніж функціональні вимоги.
Запитайте:
Чи потрібно використовувати наявну інфраструктуру?
Чи є обов’язкові технології або зовнішні провайдери?
Який бюджет на запуск і підтримку?
Чи є обмеження щодо зберігання даних?
Які вимоги до доступу та приватності?
Чи потрібно підтримувати старі клієнти?
Які строки реалізації?
Наприклад, вимога «використовувати лише вже наявну базу даних» може суттєво вплинути на спосіб зберігання черги повідомлень.
Абстрактні формулювання легко зрозуміти неправильно. Тому корисно просити конкретні приклади.
Запитання:
Покажіть приклад успішного сценарію.
Який приклад помилки є найважливішим?
Що має побачити користувач?
Які дані система отримає на вході?
Який результат вважається правильним?
Нечітка вимога:
«Система не повинна надсилати зайві повідомлення».
Уточнення:
Що вважається зайвим повідомленням?
Чи можна надсилати те саме повідомлення на два пристрої?
Чи потрібно об’єднувати кілька подій в одне повідомлення?
Скільки разів дозволено повторити доставку?
Що робити, якщо користувач повторно відкрив замовлення?
Після обговорення вимогу можна сформулювати точніше:
«Для однієї зміни статусу замовлення система створює одне логічне повідомлення. Повторні спроби доставки цього повідомлення не вважаються новими повідомленнями».
Під час обговорення не всі факти відомі. Частину значень доводиться припускати.
Наприклад:
очікується до 100 000 активних користувачів;
зовнішній провайдер підтримує повторну доставку;
подія про замовлення не змінюється після публікації;
користувач може мати кілька пристроїв.
Припущення потрібно явно записувати. Інакше різні учасники команди можуть спиратися на різні уявлення про систему.
Для кожного припущення корисно зазначити:
саме припущення;
чому воно потрібне;
як його перевірити;
що зміниться, якщо воно виявиться неправильним.
Після уточнювальної розмови вимоги можна записати в структурованому вигляді:
const requirements = {
goal: "Повідомляти покупця про зміну статусу замовлення",
users: ["покупець"],
mainScenario: [
"Сервіс замовлень публікує подію про зміну статусу",
"Сервіс сповіщень знаходить налаштування покупця",
"Сервіс надсилає push-сповіщення",
"Результат доставки записується"
],
functional: {
required: [
"Приймати події про зміну статусу замовлення",
"Надсилати push-сповіщення",
"Зберігати результат доставки"
],
later: [
"Додати налаштування типів сповіщень",
"Додати SMS-канал"
]
},
nonFunctional: {
deliveryTimeSeconds: 60,
expectedEventsPerMinute: 10000,
retryAttempts: 3
},
outOfScope: [
"Створення замовлення",
"Редагування профілю користувача",
"Реалізація push-провайдера"
]
};
console.log("Мета:", requirements.goal);
console.log("Обов'язкових функцій:", requirements.functional.required.length);
console.log("Подій за хвилину:", requirements.nonFunctional.expectedEventsPerMinute);
console.log("Поза межами:", requirements.outOfScope.join(", "));Цей опис не є архітектурою. Він фіксує домовленості, на основі яких архітектуру можна створювати.
Перед переходом до проєктування перевірте, чи можна відповісти на такі запитання:
Хто користувач системи?
Який основний сценарій?
Яка подія запускає процес?
Який результат очікується?
Що відбувається у разі помилки?
Які вимоги обов’язкові?
Які функції відкладені?
Де проходять межі системи?
Яке очікуване навантаження?
Які вимірювані вимоги до швидкості та надійності?
Які зовнішні системи використовуються?
Які припущення ще потрібно перевірити?
Якщо на важливе запитання немає відповіді, це не завжди означає, що роботу потрібно зупинити. Але невизначеність треба зафіксувати й зрозуміти, як вона може вплинути на дизайн.
Для практичного використання можна дотримуватися такого порядку:
Попросити описати мету функції.
Визначити користувачів і головні сценарії.
Уточнити вхідні дані та очікуваний результат.
Розглянути успішні та помилкові випадки.
Визначити обов’язкові й другорядні функції.
Окреслити межі системи.
Уточнити навантаження та нефункціональні вимоги.
Обговорити зовнішні залежності й обмеження.
Записати припущення та відкриті питання.
Повторити вимоги власними словами й отримати підтвердження.
Останній крок особливо важливий. Попросіть співрозмовника підтвердити короткий підсумок:
«Правильно я зрозумів, що в першій версії ми обробляємо лише зміни статусу замовлення, надсилаємо push-сповіщення, робимо до трьох повторних спроб і не реалізуємо SMS?»
Так можна виявити непорозуміння до початку розробки.
Погано:
«Для цього нам потрібна Kafka».
Спочатку потрібно з’ясувати сценарії, обсяг навантаження, вимоги до доставки та наявні обмеження. Технологія є наслідком вимог, а не їх заміною.
Розробник може сам припустити, що:
сповіщення потрібні всім користувачам;
достатньо одного каналу;
повідомлення можна втрачати;
повторна доставка неважлива.
Кожне таке припущення може змінити архітектуру. Якщо відповідь невідома, її потрібно записати як відкрите питання.
Питання «Які ще потрібні функції?» часто дає неповну відповідь. Краще розглядати конкретні сценарії:
Що відбувається після успіху?
Що відбувається після помилки?
Що бачить користувач?
Що буде, якщо дія повториться?
Що буде, якщо зовнішній сервіс недоступний?
Без визначених меж будь-яка система може нескінченно розширюватися. Потрібно явно записувати, що входить до першої версії, а що залишається відповідальністю інших систем.
Функція може бути правильною з погляду бізнес-логіки, але непридатною через низьку швидкість, нестабільність або надмірні витрати. Вимоги до продуктивності, доступності та надійності треба уточнювати так само, як і функціональність.
Навіть детальна розмова не гарантує, що всі однаково зрозуміли вимоги. Наприкінці потрібно коротко повторити висновки та зафіксувати погоджену версію.
Уточнення вимог — це перетворення загального запиту на конкретний опис системи.
Потрібно:
зрозуміти мету та користувачів;
описати основні сценарії;
розглянути успішні й помилкові випадки;
визначити пріоритети;
окреслити межі системи;
розділити функціональні та нефункціональні вимоги;
оцінити навантаження;
зафіксувати обмеження й припущення;
перевірити спільне розуміння вимог.
Добре поставлені запитання зменшують кількість неправильних припущень і допомагають створити архітектуру, яка відповідає реальній проблемі, а не лише її нечіткому опису.