Моделирование данных: базовые критерии при проектировании

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

Структуризация

Моделирование данных: базовые критерии при проектировании

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

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

Именно жёсткость позволяет структурированным системам стремиться оставаться структурированными. И чем удачней организация, тем сильней проявляется это свойство.

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

Что нужно для хорошей организации:

  • Сформировать словарь предметной области. Язык предметной области (ubiquitous language), единство терминологии — это кости скелета системы. Расположите термины и их определения там, где они чаще всего используются. Например, в корне Git-репозитория. На ревью жёстко пресекайте любые вольности с терминологией.
  • Сформулировать соглашение об именовании. Единство стиля, единство подхода задаёт узнаваемую форму и устраняет разночтения и недопонимания. Некоторые IDE позволяют сохранять правила именования в Git-репозиторий, чтобы ими пользовалась вся команда. Дополнительно можно создать модульные тесты на проверку структуры.
  • Выбрать корректный критерий структуризации. Важность данного требования трудно переоценить, т.к. оно задаёт направление развития, определяет точки роста. Для этого нужны хорошие познания предметной области или, как минимум, проблематики. Согласитесь, что иначе предусмотреть логические слои или очертить ограниченные контексты будет крайне затруднительно. Подобные решения обязательно отражайте в ADR и технической документации.

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

Структура — важная составляющая для функционального роста системы. Именно по этой причине в основе известных подходов моделирования данных лежит определение способа организации данных. Например, Kimball's modeling, Inmon's modeling, Data Vault. Между тем, отсутствие единственно верного подхода подчёркивает, что нет универсальной и всеобъемлющей структуры, которая бы подходила всем. Мы, как архитекторы и разработчики, должны выбрать наиболее подходящий вариант, исходя из условий и ограничений.

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

Моделирование данных: базовые критерии при проектировании

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

Что нужно для переиспользования:

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

Например, стоит или нет выделять адрес клиента в отдельный элемент (Value Object или Entity)? Или лучше поместить эти данные in-plane в агрегат клиента? Если добавить отдельный элемент, то что делать, когда адрес может быть указан частично? Или когда адрес не может быть изменён, т.к. является частью бизнес-события, допустим, "адрес платежа". Даже в таком простом примере очень много нюансов.

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

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

Моделирование данных: базовые критерии при проектировании

Модель данных должна соответствовать характеру ее использования. Любое расхождение с этим приводит к снижению производительности.

Такое часто наблюдается при использовании одной и той же модели для принципиально разных целей. Классический пример: сырые данные (OLTP) используются для построения отчётов (OLAP).

Моделирование не должно быть в отрыве от возможностей используемой базы данных. Иначе это будет то, на что чаще всего похоже использование ORM: швейцарский нож, который может многое, но имеет кучу ограничений — недонож, недоштопор, недоотвертка. (Заранее прошу прощения, если задел чувства верующих.)

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

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

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

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

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

Я постарался описать моменты, на которые обращаю внимание в работе. Получается ли у меня всегда всё делать идеально? Нет, конечно. Есть разные преграды и обстоятельства, приходится идти на вынужденные компромиссы. Однако, главное — видеть цель и идти к ней.

P.s. Посмею напомнить, что у меня есть Telegram-канал "Архитектоника в ИТ", где я публикую материал на похожие темы примерно раз в неделю. Подписчики меня мотивируют, но ещё больше мотивируют живые дискуссии, ведь именно в них рождается истина. Поэтому подписывайтесь на канал или на мой блог здесь. Будем обмениваться опытом и мнениями. ;-)

1 комментарий