Рекомендация: Обратное проектирование реляционных баз данных
Описание этапов обратного проектирования базы данных и связи получившихся таблиц модели данных с классами модели проектирования.
Взаимосвязи
Связанные элементы
Основное описание

Введение

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

Основные этапы обратного проектирования базы данных и преобразования получившихся элементов модели данных в элементы модели проектирования:

  • Создание физической модели данных с таблицами, представляющими физическую схему данных, хранящихся в базе данных. Этот этап может выполняться автоматически средствами, поставляемыми с Relational Database Management System (RDBMS) или современными средствами визуального моделирования.
  • Преобразование таблиц физической модели данных в классы модели проектирования. Для выполнения этого этапа сначала используются специальные средства автоматизации, а затем производится ручная корректировка.
  • Определение связей между классами в модели проектирования.
  • Определение подходящих операций в классах модели проектирования на основе действий, выполняемых над соответствующими элементами модели данных.
  • Организация классов модели проектирования подсистемы и пакеты (при необходимости).

Обратное проектирование базы данных RDBMS или сценария DDL для получения модели данных

Результатом обратного проектирования базы данных или сценария на языке определения данных (Data Definition Language - DDL) обычно является набор элементов модели (таблиц, представлений, хранимых процедур и т.д.). В зависимости от сложности базы данных может потребоваться разделить полученные элементы модели на пакеты, содержащие логически связанные наборы таблиц.

Преобразование модели данных в модель проектирования

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

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

Элемент модели данных 

Соответствующий элемент модели проектирования 

Таблица  Класс 
Столбец  Атрибут 

Неидентифицирующая взаимосвязь 

Ассоциация 

Таблица пересечений

 

Класс ассоциации

Ассоциация "многие-ко-многим"

Полная ассоциация 

Идентифицирующая взаимосвязь 

Агрегирование 

Кардинальное число 

 

Множественность 

 
Контрольное ограничение с перечислением  Класс <<ENUM>> 
Схема  Пакет 

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

Преобразование таблицы в класс

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

Пример

Рассмотрим таблицу Customer, имеющую следующую структуру:

Имя столбца Тип данных
Customer_ID Number
Name Varchar
Street Varchar
City Varchar
State/Province Char(2)
Zip/Postal Code Varchar
Country Varchar

Структура таблицы Customer

Для таблицы создается класс с таким же именем, Customer, имеющий следующую структуру:

Определение класса Customer

Первоначальная версия класса Customer

В первой версии класса Customer для каждого столбца таблицы Customer в нем присутствует соответствующий атрибут. Область видимости всех таких атрибутов - public, т.к. возможен запрос к любому столбцу таблицы.

Значок в виде знака "+" слева от атрибута означает, что область видимости последнего - 'public'. По умолчанию все атрибуты, получаемые при преобразовании таблиц RDBMS, должны быть общедоступными, так как в RDBMS разрешено делать запросы ко всем столбцам.

Идентификация внутренних и неявных классов

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

Пример

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

Диаграмма описана в сопровождающем тексте.

Класс Customer после выделения из него класса Address

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

Внешние ключи

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

Пример

Предположим, что таблица Order имеет следующую структуру:

Имя столбца  Тип данных 
Number  Number 
Customer_ID  Varchar 

Структура таблицы Order

В таблице Order столбец Customer_ID является внешним ключом. Он содержит первичный ключ таблицы Customer, связывающий ее с Order. Это представляется в модели проектирования следующим образом:

Диаграмма UML, описанная ниже.

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

Внешний ключ представляется в виде ассоциации между классами Order и Item.

Отношение "многие-ко-многим"

В моделях данных RDBMS отношения "многие-ко-многим" представляются таблицей объединения (join table), или таблицей связей (association table). Таким образом, отношения "многие-ко-многим" представляются с помощью вспомогательных таблиц с первичными ключами двух объединяемых таблиц. Такие вспомогательные таблицы нужны из-за того, что поле внешнего ключа может содержать только один первичный ключ. Если одна запись связана с несколькими записями в другой таблице, и наоборот, то возникает необходимость в таблице связей.

Пример

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

Таблица Product
Имя столбца Тип данных
Product_ID Number
Name Varchar
Описание Varchar
Price Number
Таблица Supplier
Имя столбца Тип данных
Supplier_ID Number
Name Varchar
Street Varchar
City Varchar
State/Province Char(2)
Zip/Postal Code Varchar
Country Varchar

Структура таблиц Product и Supplier

Для связи этих таблиц в целях поиска продуктов, доступных у заданного поставщика используется таблица Product-Supplier.

Таблица Product-Supplier
Имя столбца  Тип данных 
Product_ID  Number 
Supplier_ID  Number 

Структура таблицы Product-Supplier

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

В модели проектирования эта вспомогательная таблица является избыточной, поскольку объектная модель позволяет представлять отношения "многие-ко-многим" напрямую. На рисунке показаны классы Supplier и Product и их взаимосвязь. Кроме того, на нем показан класс Address, извлеченный из Supplier в соответствии с рекомендациями, оговоренными ранее.

Диаграмма UML, описание в заголовке.

Классы Product и Supplier

Обобщение

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

Пример

Рассмотрим таблицы SoftwareProduct и HardwareProduct:

Таблица Software Product
Имя столбца  Тип данных 
Product_ID  Number 
Name  Varchar 
Description  Varchar 
Price  Number 
Version  Number 
Таблица Hardware Product
Имя столбца  Тип данных 
Product_ID  Number 
Name  Varchar 
Description  Varchar 
Price  Number 
Version  Number 


Таблицы SoftwareProduct и HardwareProduct

Общие столбцы выделены синим цветом. Как видно, общей является большая часть обоих таблиц и они различаются только одним полем. Эту общность можно представить выделением общего класса Product и объявление классов SoftwareProduct и HardwareProduct подклассами Product:

Диаграмма описана в сопровождающем тексте.

Классы SoftwareProduct и HardwareProduct - потомки базового класса Product

Соберем все основные классы системы заказов вместе.

Диаграмма, описанная в тексте.

Сводная диаграмма классов для системы заказов

Репликация поведения RDBMS в модель проектирования

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

  1. Создайте методы доступа (get и set). Необходимо иметь возможность задавать, изменять и запрашивать значения атрибутов объектов. Это необходимо, поскольку к атрибутам объекта можно обращаться только через методы, предоставляемые его классом. При создании операций, устанавливающих значение атрибута, не забудьте реализовать проверку на удовлетворение условиям, накладываемым на значение поля в таблице. Если такая проверка не требуется, то просто зафиксируйте возможность изменения и получения значений атрибутов, указав для них область видимости "public", как это было сделано в диаграммах выше (значком слева от имени атрибута).
  2. Создайте операции, работающие с классом, соответствующие хранимым процедурам, работающим со связанной таблицей. Хранимые процедуры - это функции, исполняемые в DBMS. Они должны быть транслированы в модель проектирования. Если хранимая процедура работает только с одним классом, объявляйте соответствующую ей операцию с такими же параметрами и таким же возвращаемым значением. Документируйте поведение хранимой процедуры в созданной операции, указав в описании метода то, что операция реализуется хранимой процедурой.
  3. Создайте операции для управления ассоциациями между классами. Если два класса связаны между собой, должен быть способ создавать, изменять и удалять ассоциации между ними. Связь между объектами осуществляется с помощью ссылок на объекты, поэтому для создания ассоциации между Order и LineItem (т.е. добавить LineItem в Order), должна вызываться операция объекта Order, которой будет передаваться объект LineItem (например, Order.add(aLineItem)). Также должна быть возможность удаления и обновления ассоциации (Order.remove(aLineItem) и Order.change(aLineItem,aNewLineItem)).
  4. Удаление объектов. Если целевой язык поддерживает явное удаление, добавьте в деструктор класса код проверки целостности связей. В случае, если в базе данных существуют правила сохранения целостности связей, например, каскадное удаление связанных записей, соответствующее поведение необходимо отразить в задействованных классах. Например, в базе данных может быть следующее правило: при удалении Order все связанные LineItem также должны удаляться. Если целевой язык поддерживает сбор мусора, создайте механизм удаления строк из таблиц при освобождении связанного объекта в рамках сбора мусора. Обратите внимание, что корректно реализовать это достаточно трудно, поскольку вам потребуется реализовать механизм гарантирования того, что среди подключенных клиентов базы данных нет имеющих ссылки на удаляемый из памяти объект. В данном случае не следует полагаться на механизм сбора мусора среды выполнения/виртуальной машины, т.к. это всего лишь такой же клиент, как и любые другие.
  5. Поведение, требуемое для запросов. Проанализируйте операторы Select, использующиеся для обращения к базе данных, для получения картины того, как информация получается и обрабатывается. Для каждого столбца, непосредственно возвращаемого оператором Select, установите свойство public связанного атрибута равным true; для всех остальных атрибутов укажите private. Для каждого динамически вычисляемого столбца в операторе Select создайте операцию в связанном классе, рассчитывающую и возвращающую соответствующее значение. В число рассматриваемых операторов включите встроенные в представления.

Организация элементов в модели проектирования

Класс проектирования, создаваемые в результате преобразований "таблица - класс", следует организовывать в модели проектирования в пакеты проектирования и/или подсистемы проектирования, на основе общей архитектуры приложения. См. Понятия: Разделение на уровни и Понятия: Архитектура ПО.