Підхід, орієнтований на дані, з сценарним управлінням до проектування систем

system design
Kirill Latish
Kirill Latish
LinkedIn
Share

Досліджуйте підхід, орієнтований на дані, з управлінням сценаріями до проектування систем, який підкреслює ясність та ефективну комунікацію між командами. Дізнайтеся, як відокремити спостереження за даними від їх маніпуляції.

Чому розділення спостереження та маніпуляції є потужною відправною точкою

При проектуванні програмних систем багато команд відразу переходять до технологій, фреймворків або мікросервісів.

Але більшість систем стають значно простішими для розуміння, якщо почати з одного простого спостереження:

Будь-яка інформаційна система може бути описана як два підмножини процесів:

  • Спостереження за даними (читання інформації)

  • Маніпуляція даними (зміна стану)

Іншими словами, кожна система є по суті машиною читання-запису.

Ця перспектива відображає давній принцип проектування, який іноді підсумовують як “відокремлення запитів від повідомлень.”

  • Запити ставлять питання і повертають інформацію.

  • Команди змінюють стан системи.

Ця ж ідея з'являється на архітектурному рівні в CQRS (Сегрегація відповідальності запитів та команд), шаблон, описаний Мартіном Фаулером. CQRS пропонує відокремити моделі, які використовуються для оновлення інформації, від тих, що використовуються для її читання.

Однак Фаулер також застерігає, що CQRS може ввести значну складність і не повинен використовуватися за замовчуванням.

Отже, ключове усвідомлення таке:

Розділення спостереження та маніпуляції є надзвичайно потужним як інструментом проектного мислення, навіть якщо ви ніколи не реалізуєте повну інфраструктуру CQRS.

Коли його використовують як робочий процес для проектування систем, він створює ясність між командами та допомагає запобігти архітектурній плутанині.


Практичний робочий процес проектування систем

Практичний робочий процес, який підходить для багатьох систем, виглядає так:

  1. Зробіть дані явними

  2. Зробіть зміни стану явними

  3. Перевірте архітектуру на реальних сценаріях

Ці три кроки формують основу надійного процесу проектування систем.


Крок 1 — Модель даних як спільна мова

Одним з найпоширеніших джерел плутанини в обговореннях проектування систем є наступне:

Усі говорять про одну й ту ж функцію, але кожна людина уявляє іншу реальність даних.

Моделювання доменів вирішує цю проблему, створюючи спільний словник.

У проектуванні, орієнтованому на домен, це відомо як Універсальна мова — спільна мова, яку використовують розробники та експерти з домену, яка безпосередньо відображається на моделі програмного забезпечення.

Корисний спосіб почати простий:

Почніть з переліку основних сутностей та їх полів.

Це не означає, що потрібно відразу переходити до реалізації SQL.

У професійному моделюванні даних моделі зазвичай розвиваються через три рівні:

Рівень

Призначення

Концептуальний

Які сутності існують в домені

Логічний

Зв'язки між сутностями

Фізичний

Деталі реалізації бази даних

Початок з грубої чернетки проекту з переліком таблиць та полів часто є найшвидшим способом для команд досягти згоди.


Чому підхід “Таблиці в першу чергу” працює (якщо розглядати як чернетку)

Ранній перелік таблиць змушує ставити конкретні питання:

  • Які реальні сутності?

  • Що ідентифікує кожен об'єкт?

  • Які поля є необов'язковими, а які обов'язковими?

  • Що змінюється з часом?

  • Що ніколи не повинно змінюватися?

Цей підхід узгоджується з початковою мотивацією, що стоїть за моделюванням сутностей-взаємозв'язків, яке ввело діаграми для представлення семантики реальних даних.

Мета не полягає в тому, щоб відразу спроектувати ідеальну схему.

Мета полягає в тому, щоб створити спільну ментальну модель.


Шаблон мінімальної чернетки таблиці

При складанні чернеток сутностей постійно фіксуйте кілька ключових елементів:

Ідентичність

  • Стратегія первинного ключа (UUID, ціле число, натуральний ключ)

Життєвий цикл

  • created_at

  • updated_at

  • status або deleted_at

Власність

  • user_id

  • org_id

  • workspace_id

Взаємозв'язки

  • Зовнішні ключі

  • Підказки кардинальності

Обмеження

  • unique(email)

  • негативні баланси

  • обов'язкові поля

Навіть базове проектування бази даних спирається на ці концепції для підтримки цілісності між таблицями.


Нормалізуйте для правильності, потім оптимізуйте під читання

Нормалізація — це не академічна теорія — це практичний інструмент, який:

  • запобігає надмірним даним

  • уникає аномалій оновлення

  • зберігає цілісність даних

Практична стратегія, що використовується в багатьох реальних системах, така:

1. Нормалізуйте записи для правильності
2. Оптимізуйте під читання пізніше за допомогою проекцій, кешів або індексів

Ця послідовність природно підходить до моделі спостереження/маніпуляції.

Ви підтримуєте правильність на шляху запису і оптимізуєте продуктивність на шляху читання за необхідності.


Приклад моделі даних

Нижче наведено спрощену схему першої чернетки для платформи навчання, схожої на SkillHub.

text
users
- id (pk)
- email (унікальний)
- display_name
- password_hash
- created_at
- updated_at

skills
- id (pk)
- slug (унікальний)
- name
- created_at

user_skills
- user_id (fk -> users.id)
- skill_id (fk -> skills.id)
- level
- evidence_url
(pk: user_id, skill_id)

courses
- id (pk)
- owner_user_id (fk -> users.id)
- title
- description
- status (draft/published)
- created_at

lessons
- id (pk)
- course_id (fk)
- title
- content_type
- content_ref
- order_index

enrollments
- id (pk)
- user_id (fk)
- course_id (fk)
- progress_percent
- enrolled_at

assessments
- id (pk)
- course_id (fk)
- type (quiz/project)
- config_json

submissions
- id (pk)
- assessment_id (fk)
- user_id (fk)
- grade
- feedback

Навіть ця неповна чернетка дозволяє обговорення про:

  • ідентичність

  • взаємозв'язки

  • стани життєвого циклу

  • інваріанти

  • аудит

Це саме те, що раннє проектування систем повинно дозволяти.


Крок 2 — Процеси: CRUD як каркас

Після визначення моделі даних наступним кроком є проектування процесів.

Практичним першим кроком є реалізація CRUD API для сутностей.

CRUD кінцеві точки забезпечують:

  • конкретний каркас системи

  • основу для аутентифікації та валідації

  • ранні прототипи UI

  • інтеграційні тестування

Але важливо зрозуміти:

CRUD є каркасом, а не завершеною архітектурою.

Багато систем зазнають невдачі не тому, що їм бракує CRUD операцій, а тому, що вони не можуть забезпечити бізнес-правила, коли сутності взаємодіють.


Уникайте “Анемічної моделі домену”

Мартін Фаулер описує поширений антипатерн, званий Анемічною моделлю домену.

Це відбувається, коли доменні об'єкти стають простими контейнерами даних, а вся бізнес-логіка живе в сервісах.

Натомість зміни стану повинні забезпечувати правила.

Приклади:

  • Ви не можете зареєструватися на неопублікований курс.

  • Ви не можете опублікувати курс без уроків.

  • Ви не можете оцінити неіснуючу подачу.

Ці правила належать до шару маніпуляції системи.

Команди повинні забезпечувати інваріанти.


Відображення CRUD на семантику HTTP

Якщо ваша система відкриває HTTP API, узгодження CRUD з семантикою HTTP покращує ясність.

Метод

Мета

GET

спостереження (безпечне)

POST

створення

PUT

заміна (ідемпотентна)

PATCH

часткове оновлення

DELETE

видалення

Використання узгодженої семантики робить поведінку при збоях передбачуваною та зменшує випадкову складність.


Розглядайте API як контракти

Якщо CRUD кінцеві точки існують, розглядайте API як контракт, а не деталь реалізації.

Використання специфікації API, такої як OpenAPI, допомагає узгодити команди щодо:

  • форматів запитів і відповідей

  • форм помилок

  • пагінації

  • фільтрації

  • версіювання

Добрий робочий процес виглядає так:

text
Модель даних
CRUD кінцеві точки
Контракт OpenAPI
Тести
Прототипи UI

Крок 3 — Архітектура, орієнтована на сценарії

Якщо існує CRUD каркас, архітектура стає реальністю, коли ви вводите сценарії.

Проектування на основі сценаріїв походить від архітектурних методів, таких як ATAM (Метод аналізу компромісів архітектури).

Замість розмитих вимог сценарії визначають стимул і відповідь.


Типи архітектурних сценаріїв

Корисні категорії сценаріїв включають:

Сценарії використання

Типові взаємодії користувачів.

Сценарії зростання

Майбутні зміни або масштаби.

Дослідницькі сценарії

Умови збою та стресові ситуації.

Багато архітектур виглядають правильними, поки не з'являються умови стресу.

Добрі архітектори думають про все це заздалегіть.


Простий шаблон сценарію

Практичний формат сценарію:

text
Назва сценарію
Джерело
Середовище
Стимул
Артефакт
Відповідь
Міра відповіді

Приклад:

text
Сценарій: Пік реєстрації

Середовище: піковий трафік
Стимул: 5000 одночасних запитів на реєстрацію
Артефакт: API реєстрації
Відповідь: успішна реєстрація
Міра: p95 затримка < 300ms

Це змушує команди визначати вимірюваний успіх.


Приклад набору сценаріїв

Реєстрація під навантаженням

  • 5000 одночасних реєстрацій

  • p95 < 300ms

  • рівень помилок < 0.5%

Правило публікації курсу

  • опублікувати курс без уроків

  • система відхиляє запит

  • без часткових записів

Продуктивність пошуку

  • користувач шукає навички

  • результати пагіновані

  • p95 < 200ms

Збій репліки бази даних

  • репліка для читання недоступна

  • повернення до первинної

  • знижена, але функціональна поведінка

Ці сценарії стимулюють обговорення про:

  • кешування

  • індексування

  • повторні спроби

  • черги

  • моделі узгодженості


Крок 4 — Проектування інтерфейсу

Загальна евристика UI:

Мінімізуйте відстань кліків до цільових дій.

Це вірно в напрямку, але неповно.

Відома “правило 3 кліків” насправді є міфом.

Дослідження зручності використання показують, що важливим є не кількість кліків, а вартість взаємодії.


Мінімізуйте вартість взаємодії

Кращі метрики включають:

  • Час на виконання завдання

  • Рівень помилок

  • Когнітивне навантаження

Три корисні закони UX, які можуть застосувати розробники:

Закон Фіттса

Великі, близькі цілі швидше досягаються.

Важливі дії повинні бути легкодоступними.

Закон Хіка

Більше виборів збільшує час прийняття рішення.

Зменшуйте або структуруйте варіанти.

Визнання замість запам'ятовування

Користувачі повинні бачити варіанти, а не запам'ятовувати їх.


Практичні принципи UI

Деякі дієві рекомендації:

  • Розміщуйте основні дії там, де вже є увага.

  • Зробіть небезпечні дії навмисними.

  • Зменшуйте перевантаження вибору за допомогою прогресивного розкриття.

  • Чітко показуйте стан системи перед тим, як просити користувачів діяти.

Потоки спостереження повинні пріоритетизувати швидкість.

Потоки маніпуляції повинні пріоритетизувати безпеку та валідацію.


Практичний стартовий пакет для проектування систем

Легкий робочий процес проектування систем може створити чотири артефакти, які розвиваються разом.


1. Дані

  • концептуальні сутності

  • перші таблиці

  • обмеження та інваріанти


2. Процеси

  • CRUD кінцеві точки

  • доменно-команди

  • контракт API (OpenAPI)


3. Сценарії

  • сценарії використання

  • сценарії зростання

  • сценарії збою

  • критерії вимірювальної відповіді


4. Інтерфейси

  • подорожі користувачів

  • метрики вартості взаємодії

  • принципи зручності використання


Чітка комунікація архітектури

Нарешті, архітектура системи виграє від узгоджених діаграм.

Один з найпрактичніших підходів — це C4 Model, який організовує діаграми на чотирьох рівнях:

  1. Контекст

  2. Контейнери

  3. Компоненти

  4. Код

Це дозволяє командам послідовно комунікувати архітектуру між ролями.

Kirill Latish
Kirill Latish
LinkedIn
Share