какое наиболее важное преимущество предоставляет персистентность объектов в приложении
Персистентность данных в объектно-ориентированных приложениях
Давнишней мечтой объектно-ориентированных программистов является удобная возможность сохранения состояния своих объектов в промежутках времени между запусками программ (эту возможность для краткости я называю персистентностью объектов). Давнишняя мечта специалистов из сообщества баз данных состоит в том, чтобы мечта программистов стала реальностью. На этом пути были пройдены этапы языков программирования баз данных, систем управления объектно-ориентированными базами данных, объектных расширений языка SQL. Однако по-прежнему объектно-ориентированные программисты сохраняют состояние объектов в простых табличных SQL-ориентированных базах данных и, естественно, страдают от «потери соответствия» концепций используемых языков программирования и SQL-ориентированных баз данных.
Весной 2008 г. редакторы порталов ODBMS.ORG и InfoQ.COM провели две виртуальные панельные дискуссии, в которых в совокупности приняли участие девять специалистов в области объектно-реляционного отображения и объектно-ориентированных систем управления базами данных. Формально дискуссии посвящались обсуждениям различных аспектов персистентности объектов в контексте языка Java, но фактически обсуждался более широкий круг вопросов, связанных с использованием баз данных в приложениях, создаваемых на объектно-ориентированных языках программирования.
Участники дискуссий (в обеих дискуссиях участникам задавались одни и те же вопросы) высказали ряд полезных, а иногда и спорных мыслей, которые, на мой взгляд, могут быть интересны российским программистам. Оригинальный текст дискуссий не слишком литературен, поэтому я не решился его переводить, а сделал, по возможности, более гладкий пересказ. Кроме того, по своему обыкновению, я включил в текст ряд гиперссылок, поясняющих смысл некоторых терминов и аббревиатур.
Итак, вашему вниманию предлагаются материалы панельной дискуссии «Персистентность Java-объектов: положение дел», в первой части которой участвовали Майк Кейт (Oracle), Тед Ньюард (независимый консультант), Карл Розенбергер (db4objects, Inc.) и Крейг Рассел (Sun Microsystems). Участниками второй части дискуссии являлись Хосе Блейкли (Microsoft), Рик Каттелл (консультант), Вильям Кук (University of Texas at Austin), Роберт Грин (Versant) и Элан Сантос (Progress Software).
Комментарии
Страницы комментариев: 1 :: 2 :: 3 :: следующая
> Так, что любой, логичный и эффективно организованный конструктив(IT ну очень для этого благодарная среда), быстренько всяким дерьмом «модернизируется» и дополняется.
Вроде всегда так было. А это значит, что нужно уметь преодолевать такое вот «сопротивление среды». Можно считать, что подход/парадигма, успешно противодействующие «модернизаторам» достигла «зрелости» 🙂
>>Проблема в том, что человеческая психика не статична и нет того предела лености, ниже которого она бы уже не могла опуститься.
> Ruby on Rails. Знаю, что многим эта среда очень нравится.
Персистентные структуры, часть 1: персистентный стек
Я заметил, что на хабре было достаточно много постов о таких классических структурах данных, как стек, очередь, хип; рассматривались так же дерево отрезков и множество различных деревьев поиска, но очень мало внимания уделялось персистентным структурам данных. В этом цикле статей я хотел бы поговорить как раз о них. Так уж сложилось, что я достаточно давно занимаюсь олимпиадным программированием, так что рассматривать я их буду с точки зрения моего опыта применения персистентных структур в этой области.
Персистентными структурами данных мы будем называть такие структуры, что при всяком их изменении остается доступ ко всем предыдущим версиям этой структуры. Очевидно, что как один из вариантов (не самый лучший, конечно) можно рассматривать полное копирование всей структуры при каждом изменении. Это чрезвычайно неэффективно как по памяти, так и по времени работы, но этот способ можно применять например на стадии тестирования более сложной организации структуры. Но тем не менее толку от такой реализации мало, поэтому далее мы, кроме всего прочего, займемся поиском более оптимальных реализаций для различных структур.
Сегодня мы рассмотрим реализацию и применение персистентного стека. В последующих статьях я расскажу о персистентной очереди, декартовом дереве и дереве отрезков, а так же мы разберем пару задач, которые решим с применением персистентных этих структур.
Персистентный стек
Решение. Самое простое и очевидное решение этой задачи — симуляция описанного процесса, т.е. честное копирование стека при каждой операции. Очевидно, что это не самое эффективное решение. Сложность одной операции составляет O(n) и количество требуемой памяти — O(n * n).
Для того, чтобы приблизиться к идее оптимального решения, можно попробовать представить стек в виде графа, где вершина — это его элемент, тогда от каждой вершины (кроме хвоста) пустим ребро в предыдущий элемент стека. Пример для стека, в который последовательно добавили ‘1’, ‘2’, ‘3’, ‘4’, ‘5’:
Рассмотрим для наглядности алгоритм на примере. Пусть изначально у нас есть один пустой стек. Для удобства, будем хранить его как «голову» с пометкой пустого стека:
Далее выполним push(1, 5). Создается новая вершина со значением 5, ссылающаяся на 1-ую:
Аналогично выполним push(2, 10) и push(1, 6):
Очевидно, что все 4 стека сейчас верно построены и легко восстанавливаются. Давайте теперь попробуем выполнить последовательно операции pop(2) и pop(3):
pop(2) возвращает 5 и копирует 1-ую вершину. Результирующий пятый стек — пустой.
pop(3) возвращает 10 и копирует 2-ую вершину: получаем шестой стек.
Очевидно, что один запрос работает за O(1) и суммарно требуется O(n) памяти, что не может не радовать.
Применение. Насколько я помню, мне встречалось несколько задач, которые можно решить с применением персистентного стека. Понятно, что из-за некоторой примитивности это структуры слишком уж сложную задачу не придумаешь, но тем не менее они существуют. Например:
N детей по очереди лепят снеговиков. Первый ребенок слепил снеговик из одного шара радиусом R1. Каждый следующий ребенок слепил такого же снеговика, как и предыдущий, но подумав немного либо добавил шар радиусом Ri, либо разрушил верхний, уже имеющийся шар. Гарантируется, что все снеговики имеют строго положительное число шаров. Входные данные — N, информация о каждом из детей о том, разрушил ли он последний шар, либо добавил свой (тогда дается и его радиус). Далее дается набор из K чисел в пределах от 1-го до N, для каждого требуется вывести последовательность шаров в снеговике с таким номером. Ограничение на N и K — миллион.
После прочтения раздела с реализацией персистентного стека решение этой задачи становится очевидным.
Заключение. Сегодня мы рассмотрели такую структуру данных, как персистентный стек и её эффективную реализацию. Это было полезно с точки зрения понимания в дальнейшем других персистентных структур и принципов их реализаций. Как уже было отмечено, в следующий статьях я планирую рассмотреть более сложные структуры, такие как персистентные очередь, декартово дерево и дерево отрезков. Сложнее структуры — сложнее и интереснее их реализации и решения с помощью них задач. Спасибо за внимание.
Автор: Рик Греган (Rick Grehan)
Опубликовано: 17.04.2007
Одна из сильных сторон объектно-ориентированного программирования – и на самом деле главная из них – предоставляемая разработчикам возможность моделирования отношений данных естественным путем. Это не значит, что процесс моделирования прост. Архитектура многих реальных систем может представлять собой сложные деревья из подсистем, взаимодействующих с другими, не менее сложными системами. Архитектура классов в таких системах может быть головокружительно запутанной, и весьма сложной в программировании.
Мы покажем, как эти сложности смягчаются при использовании ООСУБД db4o. Вы увидите, как db4o позволяет сосредоточиться на создании оптимальной структуры классов и объектов приложения. Вам не придется беспокоиться о том, что эти структуры могут мешать (или им могут помешать) операциям с БД. Другими словами, db4o обеспечивает персистентность, минимально обременяя разработчика. Никакого специального кода; никаких изменений отношений объектов в угоду БД. Просто храните объекты, которые нужно хранить; выбирайте объекты, которые нужно выбрать, и удаляйте те объекты, что больше не нужны.
Остальное сделает db4o.
Что такое db4o?
В db4o БД рассматривается как ObjectContainer. ObjectContainer ассоциируется с определенным файлом на диске. Открытие ObjectContainer – это простой вызов API: ObjectContainer db = Db4o.openFile(“
— путь к файлу БД. После завершения операций с БД, вызывается db.close(); В остальной части этой статьи предполагается, что объект ObjectContainer с названием db уже открыт.
Плоские объектные структуры
Простые объектные структуры, тем не менее содержащие множество объектов – это «плоские» структуры. Такая структуры могут включать большой массив, или, может быть, какой-нибудь связанный список. Определяя, как сохранять такую структуру, нужно сперва определить, должен ли массив (или список) постоянно находиться в памяти (здесь мы говорим об очень больших списках, включающих тысячи или миллионы вхождений). Такое определение, в свою очередь, требует определения потенциального размера списка, и прикидок, уместится ли список в доступной памяти.
Если уместится, возможно, всю штуковину можно сохранить в один прием. Иначе придется читать и записывать ее содержимое в/из БД по частям.
Пример 1. Мониторинг транзакций Web-приложения
Организация предоставляет клиентам услуги через Web-приложение. Клиентские сайты подключаются к этому приложению и отправляют ему транзакции (чтение, обновление, изменение и т.д.). Организация хочет отслеживать – в произвольное время с переменным интервалом – число и время отклика запросов к этому Web-приложению.
Разработчики этой организации создают систему мониторинга, состоящую из приложения-«заглушки», подключенного к серверу, и отдельной консоли мониторинга. Заглушка встраивается в Web-приложение и отсылает данные о транзакциях консоли (через какой-либо механизм IPC). Пользователь, запускающий консольную программу, может начать «сессию». В течение сессии заглушка отслеживает тип, поступление и отправку клиентских запросов и ответов на них. Эта информация передается на консоль, получающую, организующую и сохраняющую информацию в БД.
Впоследствии администраторы могут обратиться к БД, исследовать тенденции и создавать отчеты и графики, отражающие такую информацию, как число транзакций в различное время суток, среднее время отклика в отношении к количеству транзакций в секунду, и так далее. Организация может использовать эту информацию, чтобы определить, хорошо ли масштабируется сервер под нагрузкой.
Рисунок 1. Простая структура для моделирования сессии. Объект Session включает ArrayList объектов Transaction.
Реализация
Разработчики этого гипотетического приложения моделируют сессию, используя два класса. Один, класс Session, включает глобальную информацию о сессии: уникальное имя, дату и время начала и завершения сессии. Объект Session также содержит List с собранной информацией о транзакциях.
Класс Session выглядит так:
А класс Transaction моделирует «пакеты» данных о транзакциях, получаемые от заглушки.
Поскольку мы в первую очередь заинтересованы в том, как сохранить члены данных объектов, и только потом в поведении методов класса, код классов приведен в сокращении. Кроме того, эти классы предполагают доступность типа данных timestamp – возможно, java.sql.timestamp – а также набора констант типа int, определенных для перечисления типа транзакции type.
При начале сессии создается экземпляр объекта Session, которому присваивается уникальное имя (sessionName). Затем консоль «говорит» заглушке начать сбор данных о транзакциях. При поступлении пакета данных от заглушки консольное приложение создает новый объект Transaction, копирует в него данные и сохраняет объект в ArrayList транзакций сессии:
Здесь объект Session – это theSession, а объект Transaction – theTransaction
После завершения сессии нет ничего проще, чем сохранить её в БД db4o, и здесь мы впервые познакомимся со встроенной логикой db4o, существенно упрощающей работу программиста. Чтобы сохранить целый объект, с List и всем остальным, нужна только одна строка кода:
db4o молча обходит дерево объектов, отыскивая и сохраняя не только объект theSession, но также и все члены ArrayList транзакций.
Получение объектов сессий так же просто. db4o позволяет выполнять прямолинейные «запросы по образцу». Чтобы запросить БД db4o, создается «прототип» объекта класса, который нужно найти. Заполните подходящие поля значениями, которые нужно найти, и вызовите метод get()ObjectContainer’а.
Предположим, например, что нужно найти сессию с именем «FridayCapture”:
Пустые или нулевые поля не участвуют в запросе
Результат запроса – это ObjectSet, который можно перебирать в цикле для выборки нужных объектов. Поскольку приведенный выше запрос возвращает только один объект, его можно получить из набора напрямую:
Вторая строка приказывает db4o «активировать» theSession на глубину 2. Когда db4o активирует объект, она загружает поля объекта из БД. Так, приведенном примере, глубина активации 2 заставляет db4o выбрать не только объект theSession, но и его «дочерние» объекты (содержимое ArrayList). Указание глубины активации 3 выбирает детей и внуков объекта, 4 – детей, внуков и правнуков, и т.д.
db4o позволяет указывать, если нужно, глубину активации для всех объектов в БД, а не для каждого в отдельности, как показано выше. Здесь явная, пообъектная активация показана для объяснения концепции активации как таковой.
Вот так все просто. Вся структура объекта сохраняется одним вызовом. И всю структуру объекта можно восстановить с помощью простого, легкого для понимания API.
Это приводит нас к важному принципу:
db4o позволяет работать со структурами объекта почти так же, как если бы эти структуры находились в памяти. Для управления сохранением объектов требуется мало дополнительного кода.
Вариации на тему
Предыдущий пример был прямолинейным и функциональным, но, возможно, не идеальным. То, что все данные сессии находятся в памяти, ограничивает размер сессии объемом доступной памяти (это может быть совершенно реалистичный верхний предел, но это не относится к предмету данной статьи).
Во врезке «Как db4o обходится с утечками памяти» мы покажем, что при решении проблемы утечек памяти – которая существует независимо от того, какой back-end-движок персистентности используется – db4o не является помехой; она хорошо вписывается в решение проблемы. Ее простой механизм запросов на самом деле, значительно упрощает решение.
Удаление
Прежде, чем закончить этот раздел, нужно описать операцию, которая здесь еще не встречалась. Это позволит нам проиллюстрировать еще одно важное способность db4o.
Предположим, что нужно удалить данные сессии. Удалить один объект очень просто. Если персистентный объект Session выбран в theSession, удалить его из БД можно так:
Но удаление связанного списка произвольной длины может вылиться в громоздкий цикл. Поскольку для удаления персистентного объекта его сперва нужно выбрать, цикл будет таким:
Это работает, но это до такой степени некрасиво, что такое как-то даже не хочется реализовать.
К счастью, db4o сохраняет нашу гордость благодаря возможности «каскадного удаления». Все, что нужно сделать – это сказать db4o перед открытием БД, что мы хотим активировать каскадное удаление для конкретного класса. Например, код может выглядеть так:
– это package класса Session.
После того, как приложение выполнило этот код, открыло БД и выбрало из нее Session, подлежащий удалению, можно удалить сессию целиком – theSession и весь связанный список объектов Transaction – одним вызовом:
db4o траверсирует все дерево объектов с корнем в theSession, удаляя все дочерние объекты. В данном случае db4o пройдет до конца связанного списка, позволяя уничтожить всю цепочку объектов Transaction единственным нажатием кнопки.
Каскадное удаление существенно упрощает программирование. Но оно может нанести вред при неаккуратном обращении. Как и любая мощная возможность, каскадное удаление требует осторожности.
Сравнение с реляционными СУБД
Остановитесь на минуточку, посмотрите на примеры кода в этом разделе и прикиньте, что пришлось бы писать при использовании реляционной СУБД. Где-то должно быть определение схемы для структуры таблиц. Пришлось бы создать две таблицы – одну для данных сессии, другую – для данных транзакций. В каждой таблице нужно назначить ключевые поля, и определить в схеме отношение один-ко-многим, связывающее запись сессии с множественными записями транзакций (скорее всего придется вставить в таблицу транзакций колонку, не имеющую никакого другого назначения, кроме связи с таблицей сессий). Там будут SQL-команды INSERT, UPDATE и DELETE – и операции присваивания для перемещения данных в/из членов объектов и связывания переменных в SQL-выражениях. Выборка целой сессии потребует соединения (join). И так далее.
Короче, немалое количество кода, необходимого для перемещения данных через невидимую границу, разделяющую объектно-ориентированную программу и реляционную СУБД.
. благодаря db4o не потребуется.
Что нужно?
Здесь некоторые читатели могут заподозрить, что мы делаем из мухи слона. Данные Transaction поступают последовательно, и сохраняются также последовательно. Почему не создать последовательный файл и не записывать данные в него по мере поступления? Зачем вся эта суета с БД?
При некоторых обстоятельствах это, конечно, был бы наилучший путь. Но если вы создаете репозиторий, из которого собираетесь получать информацию в будущем, использование БД даст вам готовые возможности поиска, которые иначе придется реализовать самостоятельно.
А вот db4o позволяет найти все эти транзакции с помощью простого запроса. Предположим, что тип транзакции определяется константой READ_TRANSACTION, а код выглядит примерно так:
Это можно сделать потому, что объекты Transaction хранятся именно как объекты. Поэтому они доступны – независимо от объектов Session – через механизм запросов db4o.
Это, конечно, куда проще кодировать, чем было бы, если бы пришлось писать код для поиска по всем спискам во всех сохраненных сессиях.
Длинные деревья объектов
Одна из прелестей объектно-ориентированного программирования в том, что оно позволяет моделировать сложные и тщательно проработанные связи более естественным способом, чем пришлось бы при использовании структурного программирования (до краев набитого порождающими ошибки указателями). Некоторые из наиболее сложных структур выглядят как та или иная «древовидная» структура.
Говоря о «длинных деревьях объектов», мы имеем в виду структуры объектов, отличающиеся от упоминавшихся выше в смысле размера. Предыдущий пример был «мелким, но широким». Теперь мы займемся «глубокими» и «разветвленными» конфигурациями. То есть корневой объект ссылается на несколько дочерних объектов, у каждого из дочерних объектов тоже есть ряд потомков, и так далее, на неизвестную глубину.
Пример 2: БД материалов для электрогенераторов
Компания, производящая линейку электрогенераторов, хотела бы создать БД со списком материалов. В такой БД каждый конечный продукт «указывает» на коллекцию узлов и агрегатов. Они, в свою очередь, указывают на следующие узлы и агрегаты. Кроме того, узлы и агрегаты ссылаются на списки деталей. В результате вся структура продукта отражается в структуре узлов, агрегатов и частей, и полный обход дерева объектов показывает все составные части продукта.
Эта структура как будто специально создана для ОО БД. «Продукт» в БД естественно представляется как дерево. Таким образом, разработчики определяют три класса: Assembly, ComponentParts и RawPart.
Как db4o справляется с утечками памяти.
Пример “Мониторинг транзакций Web-приложения” в разделе «Плоские объектёные структуры» был простым и функциональным, но, возможно, не идеальным. То, что все данные сессии находятся в памяти, ставит верхний предел размера сессии – этим пределом является, конечно, объем доступной памяти.
Предположим, что разработчики определили, что приложение должно работать с произвольно большими сессиями. Следовательно, они изменят классы так, чтобы данные транзакций помещались в однонаправленный список:
Более продуманная структура. Теперь объекты Session содержат ссылку на однонаправленный список объектов Transaction.
Цель, конечно, состоит в том, чтобы помещать транзакции в БД, используя меньше памяти. При поступлении данных транзакции они присоединяются к списку – в каждом объекте Transaction есть указатель на следующие объекты, у последнего этот указатель равен null, показывая, что это заключительный объект спика – и записываются в БД. При завершении сессии в объект Session записывается метка времени, и этот объект сохраняется в БД. Вот код для этого:
Радуясь новому коду, разработчики запускают его и.
. обнаруживают, что он не работает. Все данные по-прежнему в памяти.
Внимательные программисты, видимо, заметили, что это классическая утечка памяти в Java. Поскольку объект theSession содержит ссылку на начало списка, присоединение новых объектов просто удлиняет цепочку в памяти, хотя члены списка и сохраняются в БД. Пока ссылка на начало списка находится в памяти, весь список остается в памяти.
К счастью, есть простое решение, не только устраняющее утечку памяти, но и позволяющее настроить «шаг» записи элементов списка на диск. Это решение включает:
Вот исправленный код:
Новый код создает структуру персистентного связанного списка, который может расти до произвольно больших размеров. Кроме того, размер кеша настраивается, что позволяет разработчикам регулировать потребление памяти.
Посмотрите, что именно здесь показано. Мы решили проблему утечки памяти – существующую независимо от движка персистентности – с минимумом усилий. И db4o не мешала нам, очень удачно встроилась в решение проблемы. на самом деле, ее простой механизм запросов значительно облегчил решение проблемы.
Рисунок 2.
Каждый элемент массива componentParts ссылается на элементы RawPart, где хранится информация, нужная для идентификации отдельного предмета: фирма-поставщик (или фирмы-поставщики), SKU детали и ее цена.
Если вы ищете здесь сложный кусок кода, добавляющего в БД новый предмет со всеми его потомками, то вы его не найдете. db4o может обработать эту структуру так же легко, как объекты из предыдущего раздела. Если вы создали объект узла theAssembly, а также создали и связали между собой все его составные части, вы можете поместить theAssembly в БД так:
И, как и раньше, если вы включили каскадное удаление, удалить объект Assembly со всеми потомками можно вызовом:
Заметьте, однако, что мы позаимствовали из мира баз данных понятие внешнего ключа, чтобы создать отношение между объектом ComponentParts и объектом RawPart. Их связывает между собой поле productID. Поэтому, если мы захотим получить, например, цену конкретной детали, мы напишем что-то вроде:
Рисунок 3. С помощью db4o сложные структуры объектов сохраняются в БД так же легко, как и простые – с помощью одного вызова.
То, что связь между объектами ComponentParts и RawPart – это не объектная ссылка, позволяет не удалять из БД детали при каскадном удалении узлов.
Как видите, манипуляции со сложными древовидными структурами так же просты, как манипуляции с «плоскими» массивами или списками.
Изменения структур объектов
Смысл этого известного высказывания в том, что, хотим мы того или нет, но вещи эволюционируют, и делают это, как правило, в сторону повышения сложности. Программисты, воевавшие с проектами, в которых со временем требования изменялись, понимающе кивнут головой. Если меняется структура данных, необходимые изменения кода могут быть громоздкими и привести к появлению ошибок, особенно если БД забита «старыми» данными, которые нужно сделать «новыми».
Но при использовании db4o такие изменения просты. Вернемся к первому примеру.
Пример 1 – возвращение
Спустя некоторое время организация выросла, и теперь ее серверы приложений работают в нескольких местах. Разработчиков просят расширить систему мониторинга, чтобы собирать данные одновременно с нескольких серверов.
Они, соответственно, изменяют определение класса:
В новой версии объекты Session содержат список серверов, с которых собираются данные. Кроме того, каждый объект Transaction включает идентификатор хоста. Это позволяет в одной сессии получать данные с произвольного количества серверов.
Мы решили использовать строку для идентификации хостов в каждой транзакции. Это упрощает пример. В реальности мы отнеслись бы экономнее к дисковому пространству; возможно, использовали бы однобайтовый идентификатор, и присвоили каждому серверу в сети ID от 1 до 255.
Теперь, когда сессия запущена, имена хостов хранятся в списке хостов. При поступлении транзакций каждой из них, до помещения в связанный список и записи в БД, присваивается идентификатор сервера. То, что мы показали в первом примере – механика сохранения данных в БД – останется в основном без изменений.
Изменения схемы
Впрочем, подождите. Кое-что изменилось: структура класса. Что с лучилось с данными, уже хранящимися в БД? Не потеряем ли мы всю информацию, накопленную, пока организация использовала единственный сервер? Предположим, приложение начинает запись «новых» объектов Session и Transaction в исходную БД: «вылетит» ли приложение, когда «старые» данные будут считаны в объекты новых классов? Нужно ли нам создавать новую БД, и писать приложения для конвертирования данных?
К счастью, нет. db4o ассимилирует развивающиеся классы, не теряя ни бита. Нужно только добавить новый метод к каждому из определений классов. К классу Session нужно добавить:
А к классу Transaction:
Вот так. Отряхните руки. Конверсия выполнена.
При активации объекта db4o должна создать экземпляр объекта по определению класса. В процессе создания экземпляра db4o проверяет наличие в классе метода objectOnActivate() с сигнатурой, приведенной в двух методах выше. Если db4o находит такой метод, она вызывает его в конце процесса активации. Следовательно, этот метод можно использовать для проверки содержимого созданного объекта, а также для заполнения пустых или равных null членов объекта нужными данными до передачи объекта приложению.
Таким образом, можно незаметно заставить «старые» выглядеть «новыми». Код приложения никогда не знает – и не должен знать – что производится изменение. Для приложения все объекты, полученные из БД, являются «новыми». Реально, когда код приложения их видит, они уже являются «новыми». А если их придется записывать их обратно в БД, новая версия перезапишет старую.
В приведенных выше примерах мы предполагаем, что исходный сервер приложений называется «MainServer.» Таким образом, все старые объекты Session и Transaction будут выглядеть для приложения так, как если бы все они были получены из одного источника «MainServer.»
Наконец, заметьте, что db4o позволяет использовать изменившуюся структуру объектов – на самом деле схему объектов – без загрязнения кода приложения. Изменения потребовали только два маленьких методов, запрятанных в определениях классов, и вызываемы только при необходимости, без нашего участия.
Еще раз сравниваем с РСУБД
Теперь остановимся еще раз и прикинем, что бы пришлось делать, если бы данные хранились в РСУБД. Нам бы пришлось:
На самом деле, даже non-native ООСУБД не может работать с изменившейся структурой объектов с легкостью db4o. Многих из них смесь «новых» и «старых» объектов поставит в тупик. Какого-то рода конверторы потребуются почти наверняка.
Есть соблазн сказать, что db4o заходит еще дальше. Даже если структуры объектов могут измениться прямо «на ходу», db4o управляет изменяющейся ситуацией так, что мы практически никогда не теряем равновесия. db4o позволяет аккуратно обрабатывать изменения, используя API, производящий легкий в поддержке код, и тем самым позволяет решать действительно заслуживающие внимания задачи, не тратя времени на создание вспомогательного кода.
Суммируем
Надеемся, что в этой статье нам удалось показать, что управление персистентностью объектов – благодаря db4o – очень просто. Причем очень просто, независимо от структуры сохраняемых данных.
Не то, чтобы мы хотели сказать, что эти технологии в каком-либо отношении ущербны. Но, как было показано, в db4o одной строкой кода делается то, что в РСУБД требует нескольких. А non-native ООСУБД требуют дополнительных шагов по инструментированию кода или дополнительных материалов (таких, как файлов схем), к счастью, не нужных при использовании db4o.
Проще сказать, db4o упрощает даже самые сложные задачи по сохранению объектов.
Copyright © 1994-2016 ООО «К-Пресс»