Подход к проектированию систем на основе данных и сценариев

system design
Kirill Latish
Kirill Latish
LinkedIn
Share

Изучите подход к проектированию систем, ориентированный на данные и сценарии, который подчеркивает ясность и эффективное взаимодействие между командами. Узнайте, как отделить наблюдение за данными от их манипуляции.

Почему разделение наблюдения и манипуляции является мощной отправной точкой

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

Но большинство систем становится значительно проще для понимания, если начать с одного простого наблюдения:

Любую информационную систему можно описать как два подмножества процессов:

  • Наблюдение за данными (чтение информации)

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

Другими словами, каждая система по своей сути является машиной для чтения и записи.

Эта перспектива отражает давний принцип проектирования, который иногда резюмируется как «разделение вопроса и ответа».

  • Запросы задают вопросы и возвращают информацию.

  • Команды изменяют состояние системы.

CQRS (разделение ответственности команд и запросов), паттерне, описанном Мартином Фаулером. CQRS предлагает разделить модели, используемые для обновления информации, от тех, которые используются для ее чтения.

Тем не менее, Фаулер также предупреждает, что CQRS может ввести значительную сложность и не должен использоваться по умолчанию.

Таким образом, ключевое понимание заключается в следующем:

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

При использовании в качестве рабочего процесса для проектирования систем это создает ясность между командами и помогает предотвратить архитектурную путаницу.

Mermaid diagram is empty


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

Практический рабочий процесс, который подходит для многих систем, выглядит следующим образом:

  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 (unique)
- display_name
- password_hash
- created_at
- updated_at

skills
- id (pk)
- slug (unique)
- 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 предоставляют:

  • конкретную поверхность системы

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

  • ранние прототипы пользовательского интерфейса

  • интеграционные тестовые хуки

Но важно понимать:

CRUD — это каркас, а не готовая архитектура.

Многие системы терпят неудачу не потому, что им не хватает операций CRUD, а потому, что они не могут обеспечить бизнес-правила при взаимодействии действий.


Избегайте «Анемичной модели домена»

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

Это происходит, когда объекты домена становятся простыми контейнерами данных, а вся бизнес-логика находится в сервисах.

Вместо этого изменения состояния должны обеспечивать правила.

Примеры:

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

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

  • Вы не можете оценить несуществующую подачу.

Эти правила принадлежат слою манипуляции системы.

Команды должны обеспечивать инварианты.


Сопоставление CRUD с семантикой HTTP

Если ваша система предоставляет HTTP API, выравнивание CRUD с семантикой HTTP улучшает ясность.

Метод

Цель

GET

наблюдение (безопасно)

POST

создание

PUT

замена (идемпотентный)

PATCH

частичное обновление

DELETE

удаление

Использование согласованной семантики делает поведение при сбоях предсказуемым и снижает случайную сложность.


Рассматривайте API как контракты

Как только эндпоинты CRUD существуют, рассматривайте API как контракт, а не как деталь реализации.

Использование спецификации API, такой как OpenAPI, помогает согласовать команды по:

  • форматам запросов и ответов

  • формам ошибок

  • пагинации

  • фильтрации

  • версионированию

Хороший рабочий процесс становится:

text
Модель данных
Эндпоинты CRUD
Контракт OpenAPI
Тесты
Прототипы пользовательского интерфейса

Шаг 3 — Архитектура, ориентированная на сценарии

Как только каркас CRUD существует, архитектура становится реальной, когда вы вводите сценарии.

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

Вместо неопределенных требований сценарии определяют стимул и ответ.


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

Полезные категории сценариев включают:

Сценарии использования

Типичные взаимодействия пользователей.

Сценарии роста

Будущие изменения или масштабирование.

Исследовательские сценарии

Условия сбоя и стрессовые ситуации.

Многие архитектуры выглядят правильными, пока не появляются стрессовые условия.

Хорошие архитекторы думают об этом заранее.


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

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

text
Название сценария
Источник
Среда
Стимул
Артефакт
Ответ
Мера ответа

Пример:

text
Сценарий: Пик записей

Среда: пик трафика
Стимул: 5000 одновременных запросов на запись
Артефакт: API записи
Ответ: успешная запись
Мера: p95 задержка < 300ms

Это заставляет команды определять измеримые успехи.


Пример набора сценариев

Запись под нагрузкой

  • 5000 одновременных записей

  • p95 < 300ms

  • уровень ошибок < 0.5%

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

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

  • система отклоняет запрос

  • нет частичных записей

Производительность поиска

  • пользователь ищет навыки

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

  • p95 < 200ms

Сбой реплики базы данных

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

  • падение на основную

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

Эти сценарии стимулируют обсуждения о:

  • кэшировании

  • индексации

  • повторах

  • очередях

  • моделях согласованности


Шаг 4 — Проектирование интерфейсов

Общая эвристика пользовательского интерфейса:

Минимизируйте расстояние клика до целевых действий.

Это направление верно, но неполно.

Известное «правило трех кликов» на самом деле является мифом.

Исследования удобства использования показывают, что важно не количество кликов, а стоимость взаимодействия.


Минимизируйте стоимость взаимодействия

Лучшие метрики включают:

  • Время на выполнение задачи

  • Уровень ошибок

  • Когнитивная нагрузка

Три полезных закона UX, которые могут применить разработчики:

Закон Фиттса

Большие, близкие цели быстрее достигаются.

Важные действия должны быть легкодоступны.

Закон Хика

Большее количество вариантов увеличивает время принятия решения.

Сократите или структурируйте варианты.

Признание вместо воспоминания

Пользователи должны видеть варианты, а не помнить их.


Практические принципы пользовательского интерфейса

Некоторые практические рекомендации:

  • Размещайте основные действия там, где уже находится внимание.

  • Делайте опасные действия осознанными.

  • Сократите избыток выбора с помощью прогрессивного раскрытия.

  • Ясно показывайте состояние системы перед тем, как просить пользователей действовать.

Потоки наблюдения должны придавать приоритет скорости.

Потоки манипуляции должны придавать приоритет безопасности и валидации.

Mermaid diagram is empty

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

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


1. Данные

  • концептуальные сущности

  • первоначальные таблицы

  • ограничения и инварианты


2. Процессы

  • эндпоинты CRUD

  • команды домена

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


3. Сценарии

  • сценарии использования

  • сценарии роста

  • сценарии сбоев

  • измеримые критерии ответа


4. Интерфейсы

  • пользовательские пути

  • метрики стоимости взаимодействия

  • принципы удобства использования

Mermaid diagram is empty

Ясная коммуникация архитектуры

Наконец, архитектура системы выигрывает от последовательных диаграмм.

Один из самых практичных подходов — это Модель C4, которая организует диаграммы на четыре уровня:

  1. Контекст

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

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

  4. Код

Это позволяет командам последовательно коммуницировать архитектуру между ролями.

Mermaid diagram is empty

Большинство систем по своей сути являются машинами для чтения и записи.

Когда вы:

  • делаете данные явными

  • делаете изменения состояния явными

  • тестируете проектирование на реальных сценариях

архитектура становится значительно проще для понимания.

Сочетая:

  • ясную модель данных

  • практический контракт API

  • реалистичный каталог сценариев

  • вдумчивое проектирование интерфейсов

создает повторяемый, масштабируемый метод проектирования систем под реальным давлением поставок.

И что самое важное — это сохраняет архитектуру привязанной к тому, как системы на самом деле ведут себя, а не к тому, как мы надеемся, что они будут.

Kirill Latish
Kirill Latish
LinkedIn
Share