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

Изучите подход к проектированию систем, ориентированный на данные и сценарии, который подчеркивает ясность и эффективное взаимодействие между командами. Узнайте, как отделить наблюдение за данными от их манипуляции.
Почему разделение наблюдения и манипуляции является мощной отправной точкой
При проектировании программных систем многие команды сразу же переходят к технологиям, фреймворкам или микросервисам.
Но большинство систем становится значительно проще для понимания, если начать с одного простого наблюдения:
Любую информационную систему можно описать как два подмножества процессов:
Наблюдение за данными (чтение информации)
Манипуляция данными (изменение состояния)
Другими словами, каждая система по своей сути является машиной для чтения и записи.
Эта перспектива отражает давний принцип проектирования, который иногда резюмируется как «разделение вопроса и ответа».
Запросы задают вопросы и возвращают информацию.
Команды изменяют состояние системы.
CQRS (разделение ответственности команд и запросов), паттерне, описанном Мартином Фаулером. CQRS предлагает разделить модели, используемые для обновления информации, от тех, которые используются для ее чтения.
Тем не менее, Фаулер также предупреждает, что CQRS может ввести значительную сложность и не должен использоваться по умолчанию.
Таким образом, ключевое понимание заключается в следующем:
Разделение наблюдения и манипуляции является чрезвычайно мощным инструментом проектирования, даже если вы никогда не реализуете полную инфраструктуру CQRS.
При использовании в качестве рабочего процесса для проектирования систем это создает ясность между командами и помогает предотвратить архитектурную путаницу.
Практический рабочий процесс проектирования систем
Практический рабочий процесс, который подходит для многих систем, выглядит следующим образом:
Сделайте данные явными
Сделайте изменения состояния явными
Проверьте архитектуру на реальных сценариях
Эти три шага формируют основу надежного процесса проектирования систем.
Шаг 1 — Модель данных как общий язык
Одним из самых распространенных источников путаницы в обсуждениях проектирования систем является следующее:
Все говорят об одной и той же функции, но каждый человек представляет себе разную реальность данных.
Моделирование домена решает эту проблему, создавая общий словарь.
В проектировании, ориентированном на домен, это известно как Универсальный язык — общий язык, используемый разработчиками и экспертами в области домена, который напрямую соответствует программной модели.
Полезный способ начать — это просто:
Начните с перечисления основных сущностей и их полей.
Это не означает, что нужно сразу же переходить к реализации SQL.
В профессиональном моделировании данных модели обычно развиваются через три уровня:
Уровень | Цель |
|---|---|
Концептуальный | Какие вещи существуют в домене |
Логический | Связи между сущностями |
Физический | Детали реализации базы данных |
Начать с грубого черновика таблиц и полей часто является самым быстрым способом для команд прийти к согласию.
Почему «Таблицы первыми» работают (если рассматривать как черновик)
Раннее перечисление таблиц заставляет задавать конкретные вопросы:
Какие реальные сущности?
Что идентифицирует каждый объект?
Какие поля являются необязательными, а какие обязательными?
Что меняется со временем?
Что никогда не должно меняться?
Этот подход соответствует первоначальной мотивации, стоящей за моделированием сущностей и отношений, которое ввело диаграммы для представления семантики реальных данных.
Цель не в том, чтобы сразу же спроектировать идеальную схему.
Цель — создать общий ментальный образ.
Шаблон минимальной таблицы черновика
При черновом проектировании сущностей последовательно фиксируйте несколько ключевых элементов:
Идентичность
Стратегия первичного ключа (UUID, целое число, естественный ключ)
Жизненный цикл
created_atupdated_atstatusилиdeleted_at
Владение
user_idorg_idworkspace_id
Связи
Внешние ключи
Подсказки по кардинальности
Ограничения
unique(email)негативные балансы
обязательные поля
Даже базовое проектирование базы данных основывается на этих концепциях для поддержания целостности между таблицами.
Нормализуйте для корректности, затем оптимизируйте чтение
Нормализация — это не академическая теория — это практический инструмент, который:
предотвращает избыточные данные
избегает аномалий обновления
сохраняет целостность данных
Практическая стратегия, используемая во многих реальных системах, заключается в следующем:
1. Нормализуйте записи для корректности
2. Оптимизируйте чтение позже с помощью проекций, кэшей или индексов
Эта последовательность естественно соответствует модели наблюдения и манипуляции.
Вы поддерживаете корректность на пути записи и оптимизируете производительность на пути чтения, когда это необходимо.
Пример модели данных
Ниже приведена упрощенная схема первого черновика для платформы обучения, аналогичной SkillHub.
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, помогает согласовать команды по:
форматам запросов и ответов
формам ошибок
пагинации
фильтрации
версионированию
Хороший рабочий процесс становится:
Модель данных
↓
Эндпоинты CRUD
↓
Контракт OpenAPI
↓
Тесты
↓
Прототипы пользовательского интерфейсаШаг 3 — Архитектура, ориентированная на сценарии
Как только каркас CRUD существует, архитектура становится реальной, когда вы вводите сценарии.
Проектирование на основе сценариев происходит из архитектурных методов, таких как ATAM (Метод анализа компромиссов архитектуры).
Вместо неопределенных требований сценарии определяют стимул и ответ.
Типы архитектурных сценариев
Полезные категории сценариев включают:
Сценарии использования
Типичные взаимодействия пользователей.
Сценарии роста
Будущие изменения или масштабирование.
Исследовательские сценарии
Условия сбоя и стрессовые ситуации.
Многие архитектуры выглядят правильными, пока не появляются стрессовые условия.
Хорошие архитекторы думают об этом заранее.
Простой шаблон сценария
Практический формат сценария:
Название сценария
Источник
Среда
Стимул
Артефакт
Ответ
Мера ответаПример:
Сценарий: Пик записей
Среда: пик трафика
Стимул: 5000 одновременных запросов на запись
Артефакт: API записи
Ответ: успешная запись
Мера: p95 задержка < 300msЭто заставляет команды определять измеримые успехи.
Пример набора сценариев
Запись под нагрузкой
5000 одновременных записей
p95 < 300ms
уровень ошибок < 0.5%
Правило публикации курса
опубликовать курс без уроков
система отклоняет запрос
нет частичных записей
Производительность поиска
пользователь ищет навыки
результаты пагинированы
p95 < 200ms
Сбой реплики базы данных
реплика чтения недоступна
падение на основную
сниженное, но функциональное поведение
Эти сценарии стимулируют обсуждения о:
кэшировании
индексации
повторах
очередях
моделях согласованности
Шаг 4 — Проектирование интерфейсов
Общая эвристика пользовательского интерфейса:
Минимизируйте расстояние клика до целевых действий.
Это направление верно, но неполно.
Известное «правило трех кликов» на самом деле является мифом.
Исследования удобства использования показывают, что важно не количество кликов, а стоимость взаимодействия.
Минимизируйте стоимость взаимодействия
Лучшие метрики включают:
Время на выполнение задачи
Уровень ошибок
Когнитивная нагрузка
Три полезных закона UX, которые могут применить разработчики:
Закон Фиттса
Большие, близкие цели быстрее достигаются.
Важные действия должны быть легкодоступны.
Закон Хика
Большее количество вариантов увеличивает время принятия решения.
Сократите или структурируйте варианты.
Признание вместо воспоминания
Пользователи должны видеть варианты, а не помнить их.
Практические принципы пользовательского интерфейса
Некоторые практические рекомендации:
Размещайте основные действия там, где уже находится внимание.
Делайте опасные действия осознанными.
Сократите избыток выбора с помощью прогрессивного раскрытия.
Ясно показывайте состояние системы перед тем, как просить пользователей действовать.
Потоки наблюдения должны придавать приоритет скорости.
Потоки манипуляции должны придавать приоритет безопасности и валидации.
Практический стартовый пакет проектирования систем
Легкий рабочий процесс проектирования систем может производить четыре артефакта, которые развиваются вместе.
1. Данные
концептуальные сущности
первоначальные таблицы
ограничения и инварианты
2. Процессы
эндпоинты CRUD
команды домена
контракт API (OpenAPI)
3. Сценарии
сценарии использования
сценарии роста
сценарии сбоев
измеримые критерии ответа
4. Интерфейсы
пользовательские пути
метрики стоимости взаимодействия
принципы удобства использования
Ясная коммуникация архитектуры
Наконец, архитектура системы выигрывает от последовательных диаграмм.
Один из самых практичных подходов — это Модель C4, которая организует диаграммы на четыре уровня:
Контекст
Контейнеры
Компоненты
Код
Это позволяет командам последовательно коммуницировать архитектуру между ролями.
Большинство систем по своей сути являются машинами для чтения и записи.
Когда вы:
делаете данные явными
делаете изменения состояния явными
тестируете проектирование на реальных сценариях
архитектура становится значительно проще для понимания.
Сочетая:
ясную модель данных
практический контракт API
реалистичный каталог сценариев
вдумчивое проектирование интерфейсов
создает повторяемый, масштабируемый метод проектирования систем под реальным давлением поставок.
И что самое важное — это сохраняет архитектуру привязанной к тому, как системы на самом деле ведут себя, а не к тому, как мы надеемся, что они будут.
