Гранулярность (granularity)

Введение в ORM (Object Relationship Mapping)

Лекция 8

 

Как правило любая информационная система предполагает долгосрочное хранение данных. С точки зрения программы это выражается в том, что объекты системы могут сохраняться (persistence).

Под сохранённым объектом (persistence object) мы будем подразумевать такой объект, время жизни которого заметно превышает время запуска системы.

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

Принципиальной проблемой, с которой сталкиваются разработчики современных систем является концептуальное несоответствие между объектной и реляционной моделями в которых производиться разработки современных приложений. Так, работа с БД, её проектирование происходят в терминах отношений (relations). В то время как работа на высокоуровневым программным кодом, отвечающим за реализацию бизнес логики происходит в терминах ООП (Объектно-Ориентированного Программирования). Кратко напомним, что основными преимуществами ООП являются:

  • Инкапсуляция
  • Наследование
  • Полиморфизм

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

Одной из основных задач современного разработчика ПО является преодоление барьера между этими двумя моделями с тем, что бы с одной стороны эффективно использовать промышленные СУБД, с другой – эффективно использовать преимущества ООП.

 

Существует ряд принципиальных несоответствий между объектной и реляционной моделями. Среди них:

 

  • Гранулярность (Granularity)
  • Подтипы (Subtypes)
  • Идентификация (Identity)
  • Навигация по связям (Graph Navigation)

 

Рассмотрим каждую из проблем более подробно

 

Рассмотрим ситуацию, когда нам надо представить в объектном виде и сохранять в БД следующий класс.

 

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

При таком подходе имеет место дублирование кода, не только кода отражающего колонки таблицы и поля класса, но и кода, который обрабатывает эти колонки. Проблема ещё более усугубляется когда приходиться вносить изменение, например добавить к адресу номер телефона. С точки зрения ООП имеет смысл выделить адрес в отдельную структуру, или, с т.з. языка Java – класс. Аналогичный подход – нормализация – можно применить и к таблице User, выделив адрес в отдельную таблицу. Однако, такой подход не всегда является оправданным с точки зрения производительности, но кроме того, нарушает естественную инкапсуляцию, так как адрес не является отдельной сущностью. Имеет место несоответствие гранулярности между объектной моделью и реляционной.

То, что является наиболее удобным и естественным в объектной модели, может быть неуместным в реляционной модели и наоборот. Хорошее ORM решение позволяет абстрагироваться от этой проблемы и использовать обе модели, прозрачно преобразуя классы в таблицы. Стоит отметить, что одним из решений, могущих оказать помощь в данном случае является использование типов определяемых пользователем (User Defined Types, UDT), поддержка которых предлагается во многих современных СУБД. Однако, такое решение может оказаться неудачным, ввиду того, что поддержка UDT реализована по-разному в разных СУБД, а кроме того язык SQL не предоставляет достаточно удобного способа для работы с UDT.