Как превратить бизнес-требования в эффективную схему БД без жертв

от автора

При проектировании базы данных важно не только создать таблицы и индексы, но и отразить в них бизнес-логику.

Содержание:
1. Зачем документировать процесс проектирования БД
2. От бизнес-требований к логической модели: что записывать
3. Переход к физической модели: как документировать компромиссы
4. Кейс: документирование БД сервиса подписок
5. Инструменты для поддержания документации в актуальном состоянии
6. Заключение

1. Зачем документировать процесс проектирования БД

Первое, что нужно помнить:

Бизнес-требования ≠ схема БД

Документация связывает бизнес-требования и техническую реализацию. Без нее:

  • Разработчики тратят время на reverse engineering.

  • Оптимизации превращаются в костыли.

  • Изменения в БД становятся рискованными.

Рассмотрим на примере (пример №1), когда заказчик говорит: «У пользователя может быть только одна активная подписка». Разработчик создает таблицу subscription с полем is_active.

Что забыли учесть?

  • Поле is_active не гарантирует уникальность. Почему не добавили триггер или ограничение?

  • Как обрабатывать отмену подписки? Нужно ли архивировать данные?

Через год новый разработчик добавляет подписки через INSERT, не проверяя is_active. В итоге у пользователя оказываются две «активные» подписки — баг, который могли бы предотвратить, если бы документация объясняла бизнес-правило.

Еще один пример (пример №2). Требование заказчика: «Пользователь может сменить тариф, но мы должны сохранять историю изменений для аналитики». Разработчик создает таблицы subscription и tariff и добавляет в subscriptions поле tariff_id.

Что пошло не так?

  • История изменений нигде не записывается.

Итог:

  • Через месяц аналитики просят отчет «как часто меняли тарифы», но данных нет.

  • Приходится экстренно править схему, переносить данные.

Чтобы определить, что должно быть в документации для процесса проектирования БД, начнем постепенно заполнять чек-лист.

Что должно быть задокументировано

Пример

Бизнес-сущности и их атрибуты

Подписка (subscription) — это доступ пользователя к сервису на определенный тариф. Имеет дату начала/окончания.

Ограничения

У пользователя может быть только одна активная подписка (проверяется триггером check_single_active_subscription).

Причины денормализации

Поле product_name дублируется в order_items, чтобы сохранять историческое название товара.

Сложные связи

Таблица tariff связана с tariff_history, но данные в нее попадают через триггер, а не API.

2. От бизнес-требований к логической модели: что записывать

Перейдем к логической модели. Если представить бизнес-требования как рассказ, то логическая модель  — это его грамотный технический пересказ без искажений. Ее главная задача — сохранить смысл требований в структуре БД и четко зафиксировать, почему она устроена именно так.

Ключевые элементы документирования логической модели включают следующее:

  • ER-диаграмма,

  • глоссарий,

  • принятые решения,

  • примеры данных (опционально).

Ниже приведено описание применения этих способов документирования для примера из предыдущего раздела (пример №2).

2.1. ER-диаграммы с пояснениями

Сначала определяются основные сущности по результатам анализа предметной области и бизнес-требований. По ним формируются таблицы, например, user и tariff. Далее проектируются связи между таблицами, на этом этапе могут возникнуть связующие таблицы. Так, для реализации требования хранить несколько изменений в тарифах и даты, когда они произошли, создается таблица tariff_history. 

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

После визуализации результатов анализа, описанного выше, схема проектируемой БД воплощается в виде ER-диаграммы.

Инструменты: DBML, Mermaid, Lucidchart.

2.2. Глоссарий терминов

Для синхронизации терминов и определений на проекте формируется перечень ключевых понятий. Он помогает всем участникам проекта говорить на одном языке.

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

Глоссарий дополняет ER-диаграмму. Когда ER-диаграмма показывает связи, глоссарий поясняет значение сущностей в бизнес-контексте.

2.3. Принятые решения

В процессе проектирования систем и БД часто рассматриваются разные варианты реализаций, а затем по определенным причинам выбор делает в пользу одной из них. Важно записать, что повлияло на решение, чтобы не проводить повторные анализы, не потерять контекст и не вернуть случайно ранее отвергнутые варианты.

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

Пример документирования альтернатив, которые отвергли, и почему:
«Не стали использовать триггер для автоматического создания записей в tariff_change, так как это усложняет отладку. Изменения вносятся явно через API».

Ниже небольшой чек-лист для самопроверки при документировании логической модели.

Что должно быть в документации логической модели

Пример

ER-диаграммы

Пояснение к схеме:
tariff_change связана с tariff, а не напрямую с user, чтобы избежать избыточности.
— Поле status в subscription проверяется триггером, а не ограничением, для гибкости.

Глоссарий

Термин: Смена тарифа.
Определение: Изменение тарифного плана в рамках подписки.
Пример в БД: таблица subscription_change.

Список принятых решений

Вариант: Проверять активную подписку через триггер, а не ограничение с условием.
Почему отказались: реализация с ограничением усложняет процесс модификации условий при изменении бизнес-требования и менее прозрачно для разработчиков при анализе проблем.

Примеры данных

INSERT INTO tariff (tariff_id, tariff_name, tariff_price, is_active)
VALUES (1, ‘Базовый’, 299.00, TRUE);

3. Переход к физической модели: как документировать компромиссы

После разработки фундамента, логической модели, разрабатываются решения, переводящие ее на язык конкретной СУБД. Эти решения формируют физическую модель, которая фиксирует каждое отклонение от нормализованной структуры с учетом производительности (индексы, денормализация). 

Без документации такие решения забываются. Например, в проекте онлайн-магазина электроники через полгода никто не помнит:

  • Почему в таблице orders дублируется customer_name.

  • Зачем добавлен «лишний» индекс.

  • Почему данные хранятся в неоптимальной форме.

Результат — разработчики боятся вносить изменения, а оптимизации превращаются в технический долг. Чтобы избежать потери контекста, каждое неочевидное решение рекомендуется фиксировать в трёх ключевых точках:

  1. Код/миграции (SQL-комментарии) — для разработчиков, работающих напрямую с БД.

  2. Техническая документация (README/Confluence) — общий архитектурный контекст.

  3. Схема данных (ER-диаграммы, описания таблиц) — визуальное отражение решений.

Пример №3: Документирование денормализации

Ситуация:

В идеальной схеме цена товара должна браться из таблицы products. Но возможны случаи, когда цена товара изменилась, а заказ должен сохранить старую стоимость. Для этого в order_items добавляется fixed_price.

Как и где документировать:

1. В SQL-скрипте миграции:

2. В README репозитория:

3. На схеме (например, Mermaid).

Пример №4: Обоснование индексов

Ситуация:

Добавлен составной индекс (user_id, created_at) в таблицу orders.

Как и где документировать:

1. В SQL-комментарии:

2. В документации (Confluence/Notion):

Индекс

Поля

Назначение

Эффективность

idx_user_created

user_id, created_at

Оптимизация запросов «заказы пользователя за период»

Снижение времени с 1200 мс до 50 мс

3. На схеме (например, Mermaid).

Пример №5: JSON-поля вместо реляционной структуры

Ситуация:

Поле metadata в таблице user хранит динамические атрибуты (например, источник регистрации).

Как и где документировать:

1. В SQL-скрипте миграции:

2. Страница в Confluence/Notion — для сложных решений.

Чтобы систематизировать подход, рекомендуется использовать чек-лист для проверки полноты документации. Вот ключевые категории, которые стоит учитывать:

Что должно быть задокументировано

Пример

Архитектурные решения

Репликация

Чтение из реплик для отчетов, запись только в мастер.

Шардирование

Данные пользователей шардированы по user_id для горизонтального масштабирования.

Решения по оптимизации производительности

Партиционирование

Таблица orders партиционирована по created_at для ускорения архивных запросов.

Оптимизация запросов

Индекс (user_id, status) ускоряет фильтрацию по активным пользователям.

Административные решения

Резервное копирование

Ежедневные снепшоты с retention 7 дней.

Для каждого «неидеального» решения рекомендуется указывать:
1. причину (производительность, гибкость, требования),
2. альтернативы (что отвергли и почему),
3. последствия.

4. Кейс: Документирование БД сервиса подписок

Рассмотрим практический пример проектирования БД для сервиса подписок — от бизнес-требований до физической реализации.

Бизнес-требования:

  1. Одна активная подписка на пользователя:
    Пользователь должен иметь одну активную подписку.

  2. История изменений тарифов:
    При смене тарифа должна сохраняться старая цена для аудита и аналитики.

  3. Аудит действий:
    Система должна фиксировать изменений подписки (создание, продление, отмена) с указанием автора действия.

Логическая модель

ER-диаграмма в Mermaid:

Пояснения к диаграмме:
1. История изменений тарифов
Таблица tariff_history хранит только изменения цены, а не весь тариф, чтобы избежать избыточности.
2. События подписок
Таблица subscription_change фиксирует все действия (создание, отмена, изменение тарифа) для аудита.

Глоссарий терминов:

Термин

Определение

Источник

Таблица БД

Подписка

Доступ пользователя к сервису

Из бизнес-требования: «Пользователи должны иметь возможность подписываться на сервис»

subscription

Тариф

План с ценой и условиями

Из интервью с Заказчиком

tariff

Историчность

Правило хранить все изменения цены

Из бизнес-требования: «При смене тарифа должна сохраняться старая цена для аудита и аналитики»

tariff_history

Физическая модель

1. Денормализация цены в подписку

Проблема:
Цена тарифа может измениться, но стоимость активной подписки должна оставаться неизменной.

Решение:
Добавляем поле current_price в таблицу subscription, дублируя данные из tariff.

Документирование:

2. Триггер для проверки активной подписки

Бизнес-правило: У пользователя может быть только одна активная подписка.

Реализация: через SQL-скрипты.

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

Альтернативы:

  • Проверка на уровне приложения (риск: race condition).

  • Ограничение через частичный индекс (сложность поддержки).

3. История изменений тарифов

Решение:

Почему не JSON?

  • Структура данных предсказуема (цена + метаданные).

  • Упрощает аналитические запросы (фильтрация по дате/пользователю).

Итог

  1. Бизнес-правила зафиксированы в:
    1.1 SQL-комментариях (триггеры, ограничения).
    1.2 Отдельном документе (database_schema.md).

  2. Компромиссы объяснены:
    2.1 Почему выбрана денормализация.
    2.2 Почему история тарифов — отдельная таблица.

  3. Примеры запросов ускоряют onboarding новых разработчиков.

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

Документирование информации эффективно только в том случае, когда в документации содержится актуальная информация. Есть два основных подхода, которые могут помочь в поддержании ее актуальности.

5.1 Автоматическая генерация документации

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

  • Встроенные средства PgAdmin позволяют экспортировать актуальную структуру таблиц с типами полей, ограничения, индексы, а также SQL-комментарии к объектам БД.

  • Визуализация: позволяет описывать схему в декларативном формате.

5.2 Changelog

Это еще один вариант поддерживать документацию в актуальном состоянии. Например, ведение migrations.md в репозитории с изменениями. А для сложных изменений добавление ссылки на задачи (тикеты) или обсуждения. 

В итоге, инструменты помогут сделать документацию более полезной:

  • Автогенерация сэкономит время и снизит риск расхождений.

  • Changelog сохранит контекст изменений для всей команды.

6. Заключение

Проектирование БД — это не только создание таблиц и индексов, но и документирование решений, чтобы разработчики понимали, почему схема устроена именно так, аналитики могли самостоятельно писать запросы, а новые члены команды быстрее входили в проект.

Ключевые шаги:

  • Записывайте бизнес-правила в логической модели (ER-диаграммы, глоссарий).

  • Объясняйте компромиссы в физической реализации (SQL-комментарии, README).

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

Итог:

Документация — это живой инструмент. Если она встраивается в процесс разработки, то помогает сохранить целостность проекта на всем его жизненном цикле.


ссылка на оригинал статьи https://habr.com/ru/articles/920916/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *