Pull to refresh

Как правильно организовать распределенное проектирование БД?

Reading time4 min
Views3.7K
В последнее время я занимался развертыванием проектов на базе таких приложений как Magento и Odoo (OpenERP). Оба приложения позволяют сторонним разработчикам создавать модули/расширения, встраиваемые в основное приложение. С Odoo у меня опыта поменьше, но вот с Magento я общался довольно плотно. И вопрос, который у меня возник, я вынес в заголовок статьи.

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

Границы применимости


Рассмотрим сообщество разработчиков таких web-приложений, как Magento (WordPress, Drupal, Joomla, ...). В сообществе есть группа разработчиков, развивающая базовый функционал приложения, есть множество групп разработчиков, создающих свои собственные расширения базового функционала, есть интеграторы, которые пытаются в соответствии с пожеланиями конечного пользователя собрать воедино базовый функционал и все необходимые расширения.

Разработчики базового функционала и расширений, как правило, манипулируют данными, сохраняемыми в реляционных базах данных. Реляционные БД позволяются более строго описывать структуры данных — накладываемые ограничения (foreign keys, unique indexes) облегчают разработчикам понимание предметной области (что хотел изобразить автор конкретной структуры) и затрудняют неправильное использование уже существующих структур. Они не обладают такой же масштабируемостью и гибкостью, как хранилища типа «ключ-значение», но их возможностей хватает для проектов того уровня, в которых они применяются (десятки и сотни одновременно работающих пользователей, объемы данных ограничиваются дисковой подсистемой физического сервера), а гибкость приносится в жертву упорядоченности, которая позволяет повысить конечную сложность разработок.

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

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

Каждый модуль (базовый или расширение) проходит свой путь развития, на котором происходит изменение используемых им структур данных. Вот, например, выдержка из списка файлов, изменяющих структуру данных в базе для Magento-модуля Mage_Core:

install-1.6.0.0.php
...
upgrade-1.6.0.1-1.6.0.2.php
upgrade-1.6.0.2-1.6.0.3.php
upgrade-1.6.0.3-1.6.0.4.php


Здесь для получения итоговой структуры данных версии 1.6.0.4 нужно сначала применить скрипт install-1.6.0.0.php, а затем по очереди все скрипты от upgrade-1.6.0.1-1.6.0.2.php до upgrade-1.6.0.3-1.6.0.4.php (почему нет upgrade-1.6.0.0-1.6.0.1.php — я не знаю). Скрипты через механизм Magento ORM добавляют новые элементы структуры (таблицы, поля, индексы), изменяют существующие, удаляют устаревшие. Подобные скрипты могут быть использованы в любом расширении Magento — базовый функционал их обнаружит и применит в нужной последовательности. С учетом межмодульных зависимостей. В целом, вполне успешный подход, позволяющий достаточно независимо строить весьма сложные структуры данных (порядка сотен таблиц). Я со своей стороны вижу два момента, которые хотелось бы улучшить.

Пространства имен


Во-первых, использовать пространства имен (namespaces) не только на уровне модулей (Mage_Core, Mage_Catalog, ...), но и на уровне структур данных. При достаточно большом количестве разработчиков расширений вероятность возникновения таблиц с именем, допустим, group или message в различных модулях становится значимо ненулевым. Большинство крупных или толковых разработчиков дают префиксы своим структурам (aw_, amasty_, prxgt_, ...), но я видел, что некоторые модули создают таблицы с именами cc и csv. Наличие пространства имен позволяет «развязать» между модулями не только таблицы (сущности проектируемой предметной области), но и поля таблиц (атрибуты сущностей).

Декларативное описание


Во-вторых, для создания структуры данных модуля использовать не программный код (императивный подход), а xml-описание (декларативный подход) — наподобие Hibernate Mapping Files. В этом случае базовый функционал имеет возможность провести анализ xml-описаний для всех задействованных в проекте модулей без изменения структур данных в базе и выдать диагностическое сообщение в случае обнаружения каких либо несоответствий (например, модуль B добавляет атрибут/поле к некоторой сущности/таблице, определенной в модуле A, но в текущей версии модуля A эта сущность более не используется).

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

Резюме


Мой накопленный опыт развертывания проектов на базе web-приложений с использованием расширений сторонних разработчиков говорит о необходимости наличия инструмента, позволяющего различным, слабо связанным командам совместно и непротиворечиво проектировать конечную структуру базы данных. Как минимум подобный инструмент должен давать возможность развязки одноименных сущностей/таблиц различных модулей через пространство имен. Возможно, в подобном инструменте применяется декларативное описание целевой предметной области (всей или только значимой ее части). Как максимум, подобный инструмент слабо зависит от языка, на котором создано само приложение — обработку данных в одной и той же базе можно вести из различных приложений/утилит/консоли, вернее, может поддерживать несколько языков программирования (php, python, java, c#, javascript, ...).

Был бы признателен за ссылки на подобные инструменты, если таковые существуют.
Tags:
Hubs:
-1
Comments0

Articles