какое наиболее важное преимущество предоставляет персистентность объектов в приложении
Персистентные структуры, часть 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 — миллион.
После прочтения раздела с реализацией персистентного стека решение этой задачи становится очевидным.
Заключение. Сегодня мы рассмотрели такую структуру данных, как персистентный стек и её эффективную реализацию. Это было полезно с точки зрения понимания в дальнейшем других персистентных структур и принципов их реализаций. Как уже было отмечено, в следующий статьях я планирую рассмотреть более сложные структуры, такие как персистентные очередь, декартово дерево и дерево отрезков. Сложнее структуры — сложнее и интереснее их реализации и решения с помощью них задач. Спасибо за внимание.
Персистентность данных в объектно-ориентированных приложениях
Давнишней мечтой объектно-ориентированных программистов является удобная возможность сохранения состояния своих объектов в промежутках времени между запусками программ (эту возможность для краткости я называю персистентностью объектов). Давнишняя мечта специалистов из сообщества баз данных состоит в том, чтобы мечта программистов стала реальностью. На этом пути были пройдены этапы языков программирования баз данных, систем управления объектно-ориентированными базами данных, объектных расширений языка 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. Знаю, что многим эта среда очень нравится.
Персистентные структуры данных
Определение: |
Персистентные структуры данных (англ. persistent data structure) — это структуры данных, которые при внесении в них каких-то изменений сохраняют все свои предыдущие состояния и доступ к этим состояниям. |
Содержание
Уровни персистентности [ править ]
Есть несколько уровней персистентности:
В частично персистентных структурах данных к каждой версии можно делать запросы, но изменять можно только последнюю версию структуры данных.
В полностью персистентных структурах данных можно менять не только последнюю, но и любую версию структур данных, также к любой версии можно делать запросы.
Конфлюэнтные структуры данных позволяют объединять две структуры данных в одну (деревья поиска, которые можно сливать).
Функциональные структуры данных полностью персистентны по определению, так как в них запрещаются уничтожающие присваивания, т.е. любой переменной значение может быть присвоено только один раз и изменять значения переменных нельзя. Если структура данных функциональна, то она и конфлюэнтна, если конфлюэнтна, то и полностью персистентна, если полностью персистентна, то и частично персистентна. Однако бывают структуры данных не функциональные, но конфлюэнтные.
Способы преобразования структур данных в персистентные [ править ]
Есть несколько способов сделать любую структуру персистентной:
Рассмотрим для начала частичную персистентность. Для наглядности занумеруем разные версии структур данных. История изменений структуры данных линейна, в любой момент времени можно обратиться к любой версии структуры данных, но поменять возможно только последнюю версию (на рисунке она выделена синим цветом).
Сформулируем, что такое структура данных. В нашем понимании структурой данных будет называться набор узлов, в которых хранятся какие-то данные, и эти узлы связаны ссылками. Пример структуры данных — дерево. Рассмотрим, как методом копирования пути превратить дерево в персистентное.
Метод копирование пути [ править ]
Так как рассматривается сбалансированное дерево поиска, то поднимая вершину вверх при балансировке, нужно делать копии всех вершин, участвующих во вращениях, у которых изменились ссылки на детей. Таких всегда не более трех, поэтому ассимптотика [math]O[/math] [math]( \log n)[/math] не пострадает. Когда балансировка закончится, нужно дойти вверх до корня, делая копии вершин на пути.
Этот метод хорошо работает на стеке, двоичных (декартовых, красно-черных) деревьях. Но в случае преобразования очереди в персистентную операция добавления будет очень дорогой, так как элемент добавляется в хвост очереди, который достижим из всех остальных элементов. Также не выгодно применять этот метод и в случае, когда в структуре данных имеются ссылки на родителя.
Реализация на основе дерева отрезков [ править ]
На основе дерева отрезков можно построить полностью персистентную структуру данных.
Для того, чтобы изменить элемент в персистентном дереве отрезков, необходимо сделать следующие действия: спустимся в дереве от корня нужной версии до требуемого элемента, скопируем его, изменим значение, и, поднимаясь по дереву, будем клонировать узлы. При этом необходимо менять указатель на одного из детей на узел, созданный при предыдущем клонировании. После копирования корня, добавим новый корень в конец массива корней.
Метод «толстых» узлов [ править ]
Преобразование списка в персистентный за O(1) [ править ]
Будем называть узел полным, если у него есть вторая версия. Если мы хотим вставить новый элемент в середину списка (на рисунке ниже он обозначен зеленым цветом), мы должны склонировать все полные узлы слева и справа от места добавления нового узла, дойти до ближайших элементов, у которых нет второй версии и добавить им вторую версию.
Оценим амортизационное время работы такого алгоритма. У нас частично персистентная структура данных, изменять можно только ее последнюю версию. Примем функцию потенциала [math]\Phi[/math] равной числу полных узлов в последней версии.
Общий метод построения частично персистентных структур данных [ править ]
Применим методы, описанные выше, в общем случае для абстрактной структуры данных.
Получение полностью персистентных структур данных [ править ]
Для полностью персистентных структур данных применить описанный выше метод преобразования не получится, так как история создания версий не линейна и нельзя отсортировать изменения по версиям, как в частично персистентных структурах данных. Пусть мы храним историю изменения версий в виде дерева. Сделаем обход этого дерева в глубину. В порядке этого обхода запишем, когда мы входим, а когда выходим из каждой версии. Эта последовательность действий полностью задает дерево, сделаем из нее список. Когда после какой-то версии (на рисунке ниже это версия [math]6[/math] ) добавляется новая версия структуры данных (на рисунке версия [math]8[/math] ), мы вставляем два элемента в список (на рисунке это [math]+8[/math] и [math]-8[/math] ) после входа, но до выхода из той версии, когда произошло изменение (то есть между элементами [math]+6[/math] и [math]-6[/math] ). Первый элемент вносит изменение, а второй будет возвращать обратно значение предыдущей версии. Таким образом, каждая операция разбивается на две: первая делает изменение, а вторая его откатывает.
В change log «толстого» узла теперь будем добавлять два события: одно указывает на изменение, произошедшее в соответствующей версии, а другое на его отмену. События будут добавляться в change log не по номерам версий, а по их порядку в списке версий List Order Maintenance.
В какой-то момент change log «толстого» узла переполнится. Тогда нужно клонировать этот узел и нижнюю половину изменений перенести в change log склонированного узла. Первую половину изменений применяем к исходной версии узла и сохраняем в качестве исходной в склонированном узле.
Получится два узла: первый отвечает за отрезок версий до операции последнего изменения, а второй — после нее. Дальнейший порядок действий аналогичен тому, который использовался в общем методе построения частично персистентных структур данных.
Использование персистентных структур данных для решения геометрических задач [ править ]
Персистентные структуры данных используются при решении геометрических задач. Примером может служить Point location problem — задача о местоположении точки. Задачи такого рода решаются в offline и online. В offline-задачах все запросы даны заранее и можно обрабатывать их одновременно. В online-задачах следующий запрос можно узнать только после того, как найден ответ на предыдущий.
При решении offline-задачи данный планарный граф разбивается на полосы вертикальными прямыми, проходящими через вершины многоугольников. Затем в этих полосах при помощи техники заметающей прямой (sweep line) ищется местоположение точки-запроса. При переходе из одной полосы в другую изменяется сбалансированное дерево поиска. Если использовать частично персистентную структуру данных, то для каждой полосы будет своя версия дерева и сохранится возможность делать к ней запросы. Тогда Point location problem может быть решена в online.
Персистентность данных в объектно-ориентированных приложениях
Давнишней мечтой объектно-ориентированных программистов является удобная возможность сохранения состояния своих объектов в промежутках времени между запусками программ (эту возможность для краткости я называю персистентностью объектов). Давнишняя мечта специалистов из сообщества баз данных состоит в том, чтобы мечта программистов стала реальностью. На этом пути были пройдены этапы языков программирования баз данных, систем управления объектно-ориентированными базами данных, объектных расширений языка 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 :: следующая
Модели ортогональны, посему снижение порога требуемой квалификации не получается. И средства ORM/ОРП позволяют до поры до времени оставлять безнаказанной некомпетентность в области разработки баз данных.
Сергей, я думаю, имелась в виду не реализация шаблона Active Record в ROR, а собственно, шаблон проектирования, описанный, к примеру, у Мартина Фаулера в классической книге «Архитектура корпоративных приложений».
Мне кажется что логика «не используют, потому что непрофессионалы» в данном случае не подходит.
Надо идти в обратную сторону.
Когда для освоения технологии не потребуется много усилий, когда она станет легкой для использования неквалифицированнми разработчиками, вот тогда и можно утверждать, что технология вошла в жизнь.
Страницы комментариев: 1 :: 2 :: следующая
Персистентность Java-объектов: положение дел. Часть 1
В этой виртуальной панельной дискуссии редакторы InfoQ.com (Флойд Маринеску, Floyd Marinescu) и ODBMS.org (Роберто Зикари, Roberto V. Zicari) задают вопросы группе ведущих разработчиков решений персистентности по поводу их оценки положения дел в области персистентности в сообществе Java.
Майк Кейт (Mike Keith), руководитель подгруппы по спецификации EJB, основной разработчик Oracle Toplink ORM.
Тед Ньюард (Ted Neward), независимый консультант, часто публикующий в своем блоге заметки на темы ORM и персистентности.
Карл Розенбергер (Carl Rosenberger), ведущий разработчик db4objects, свободно распространяемой встраиваемой объектной базы данных.
Крейг Рассел (Craig Russell), бывший руководитель группы по разработке спецификаций Java Data Objects (JDO), разработчик процессора компонентов-сущностей (entity bean) в серверах приложений компании Sun, предшествовавших Glassfish.
Вопрос 1: По-прежнему ли перед нами стоит «проблема потери соответствия» (impedance mismatch problem)?
Майк Кейт: Потеря соответствия будет существовать до тех пор, пока объектная модель будет использоваться для чтения и записи реляционных данных. Это явление становится проблемой, если отсутствуют стратегии, технологии или инструментальные средства, позволяющие преодолеть потерю соответствия, или если эта потеря соответствия приводит к запутанным разработкам или плохой производительности. Всегда будут иметься некоторые сценарии, приводящие к этим ситуациям, просто потому, что такова природа потери соответствия. Технологии и инструментальные средства могут здорово помочь, и они действительно отвечают потребностям подавляющего большинства приложений, но они не могут превратить воду в вино.
Тед Ньюард: Безусловно. До тех пор, пока у нас имеются разные «формы» кратковременных и долговременных данных – подобно тому, как сейчас мы пытаемся использовать кратковременные данные в форме объектов и сохранять их в реляционном долговременном хранилище данных, – перед нами будет стоять проблема потери соответствия. Все проблемы несоответствия (объектной и реляционной моделей, объектной модели и иерархической модели или модели XML, иерархической и реляционной моделей), в конце концов, оборачиваются одной базовой проблемой: вколачиванием круглых предметов в квадратные или треугольные отверстия. Одно из решений состоит во включении этих разных «форм» в наши инструментальные средства, например, в добавлении в языки программирования множеств как понятий первого класса для облегчения работы с множествами в хранилище данных, но пока нет даже этого.
Карл Розенбергер: Этой проблемы нет, если вы не работаете с реляционной базой данных. Давайте взглянем на это с позиций двух конкретных языков программирования – Java и SQL.
В среде Java программист может быть очень продуктивным за счет написания небольших, простых и лаконичных методов, которые легко понимаются. В реляционной базе данных отсутствует понятие навигации, и чтобы получить что-нибудь из базы данных, нужно наизусть помнить схемы таблиц. Представьте, что требуется узнать заработную плату начальника некоторого служащего. Используя Java и IDE (Integrated Development Environment, интегрированная среда разработки) с автозаполнением, можно за несколько секунд написать код employee.department().manager().salary();
При использовании SQL для написания оператора SQL, выполняющего ту же задачу, потребовалось бы несколько минут …
SELECT e2.salary FROM
employee e1, employee e2, department
WHERE
e1.id = current_employee_id
AND
e1.department = department.id AND
department.manager = e2.id
… и нужно убедиться в том, что синтаксис не нарушен, и что не перепутаны две ссылки на таблицу employee.
Если для написания приложения требуется использовать и Java, и SQL, то ради поддержки интерфейса между двумя очень разными языками приходится жертвовать временем разработки, качеством программы, ее эффективностью и производительностью.
Накладные расходы, требуемые для поддержки двух очень разных баз кода, более чем удваивают объем требуемой работы. Кроме того, они препятствуют выполнению процессов рефакторинга и быстрой (agile) разработки. Если вы полностью принимаете объектную технологию, включая использование объектной базы данных, то у вас отсутствует потеря соответствия.
Крейг Рассел: Это зависит от области бизнеса и используемого языка. Если вы работаете на C++ и для моделирования своей прикладной области используете множественное наследование, то для хранения прикладных объектов в реляционных базах данных потребуется много работы.
Наиболее существенным фактором является то, хотите ли вы использовать прикладные Java-объекты для представления того, что уже находится в вашей базе данных, или же вы пытаетесь использовать базу данных для хранения прикладных Java-объектов. В первой ситуации большинство реляционных схем можно вполне удачно представить с использованием прикладных Java-объектов. Больше шансов на потерю соответствия появляется, если вы пытаетесь хранить прикладные Java-объекты в реляционной базе данных.
Другой областью потери соответствия является наследование. Реляционная схема не точно соответствует концепции наследования Java, хотя многие реляционные схемы на практике включают столбец-дискриминатор, который используется для различения строк разного типа. Этот метод предшествует многим решениям объектно-реляционного отображения, существующим сегодня.
Вопрос 2: Как бы вы позиционировали различные варианты обеспечения персистентности объектов в новых проектах, если принимать во внимание то, что используется в индустрии?
Майк Кейт: Если начать с предположения, что в подавляющем большинстве проектов требуется хранить данные в реляционной базе данных, то требования к средствам обеспечения персистентности в основном относятся к одной из трех категорий. Всегда имеется несколько пограничных случаев и незначительных вариантов, но эти три категории охватывают подавляющее большинство основных приложений, в которых поддерживаются персистентные Java-объекты.
1. JDBC – Огромное число разработчиков по разным причинам все еще полагается на JDBC. Может быть, им не нужен или не желателен уровень отображения, а может быть, им не разрешает пользоваться средствами отображения начальство. Независимо от причины, JDBC продолжает оставаться жизнеспособным вариантом и при использовании должным образом и в правильных целях может быть вполне пригоден для некоторых приложений.
2. Легковесные и самодельные каркасы – Иногда люди, которым требуется вручную писать код на SQL, обнаруживают, что если они образуют над SQL некоторый дополнительный тонкий слой, то это позволит сделать их код более удобочитаемым и сопровождаемым. Требованиям этих приложений может отвечать простой каркас JDBC или самодельное решение, соответствующее практике разработки и кодирования приложения.
3. ORM – Инструментальное средство объектно-реляционного отображения включает отображение модели метаданных, определяющее, каким образом состояние объектов сохраняется в базе данных и запрашивается из нее. Очень многих людей полностью устраивает технология ORM, и они пользуются ей для удовлетворения своих потребностей. Java Persistence API (JPA) является стандартным API объектно-реляционного отображения в Java EE и в не корпоративных средах Java.
С ростом популярности SOA появляется класс приложений, которым просто требуется посылать Java-объекты в приемник XML. Этот приемник может принимать форму порта Web-сервиса, процесса BPEL или некоторой очереди для более поздней обработки. Возможность отображать объекты XML обеспечивается такими стандартами, как JAXB и SDO, и имеются проекты типа Eclipse Persistence Services, в которых реализуются все эти стандарты и многие другие функциональные возможности.
Тед Ньюард: Очевидно, имеется множество вариантов, и у каждого из них есть свои достоинства и недостатки. Майк выделил три основных варианта, и я бы добавил к ним еще несколько:
1. Хранимые процедуры, при использовании которых мы погружаем всю логику хранения и выборки (а иногда и бизнес-логику, связанную с данными) в код, исполняемый внутри базы данных, где любое приложение – будь оно написано на Java, C++, C# или Ruby – подчиняется одной и той же централизованной логике. Этот подход часто комбинируется с традиционным подходом JDBC/интерфейса-уровня-вызова (call-level-interface) или объектно-реляционным отображением для упрощения вызова хранимых процедур и получения результатов.
2. Объектные базы данных (ООСУБД), хранящие в базе данных сами реальные объекты. Про ООСУБД более подробно будет говорить Карл.
Естественно, имеются и разнообразные гибридные подходы, но каждый из них обычно в основном относится к одной из упомянутых категорий.
Карл Розенбергер: Когда люди говорят о базах данных, они обычно имеют в виду корпоративные базы данных, которые обслуживают многих разных пользователей, разные приложения и языки программирования. Из-за этих унаследованных баз данных SQL останется с нами еще многие годы.
В близком будущем у нас будет иметься 5 миллиардов мобильных телефонов и только 2 миллиарда PC. Рынок приложений в устройствах (и баз данных в устройствах) опередит в своем росте соответствующий рынок для PC.
Для баз данных в устройствах принято следующее:
• они ориентируются только на один язык программирования;
• отсутствует администратор базы данных, настраивающий доступ к базе данных;
• пользователь не вводит в устройство вручную написанные запросы.
Если приложения для устройств пишутся на некотором объектно-ориентированном языке, то имеется ли какое-либо основание использовать реляционную базу данных или SQL?
Microsoft создала очень серьезный прецедент со своим проектом LINQ. Они отходят от SQL в пользу обеспечения доступа к данным как неотъемлемой концепции языка программирования.
Это является будущим для новых проектов, просто потому, что это наиболее эффективный способ разработки и сопровождения кода.
С принятием LINQ концепция функционального языка станет основным распространенным стандартом запросов к базам данных.
Будучи участником разработки объектной базы данных, я восхищаюсь этим подходом. Для нас это просто лакомый кусок: LINQ позволяет использовать в запросах обычные вызовы методов C# – можно производить навигацию. Поскольку в объектных базах данных объекты сохраняются в виде, очень близком к их представлению в основной памяти, для LINQ объектные базы данных могут быть гораздо лучше оптимизированы, чем реляционные базы данных. Там, где в объектной базе данных для навигации можно использовать непосредственный указатель, в реляционной базе данных приходится поддерживать два индекса и производить в них поиск, чтобы выполнить запрос с соединением.
LINQ – это мечта поставщиков объектных баз данных. Неожиданно появился стандарт для запрашивания данных из объектных баз данных, и теперь они могут запросто превзойти любую реляционную систему.
Нам очень хотелось бы видеть стандарт, подобный LINQ, для Java. При использовании Native Queries мы обеспечиваем очень похожий подход. Мы даем возможность использования 100% обычных средств Java при формулировке запросов к базе данных.
Лучше всего я могу судить о потребностях индустрии в областях, в которых мы видим серьезные преимущества нашего продукта:
• приложения для устройств с ограниченными ресурсами, где высокая производительность должна сопровождаться низким уровнем потребления ресурсов памяти;
• приложения со сложными классами, включающими много атрибутов и/или основанными на глубоких иерархиях наследования;
• приложения, в которых классы часто подвергаются рефакторингу, и поддержка реляционной базы данных и отображения была бы ночным кошмаром;
• приложения, нуждающиеся в очень быстром выходе на рынок;
• приложения Rich Client, написанные с использованием технологии Eclipse RCP, JavaFX или Silverlight.
Поскольку в этих областях наши пользователи кажутся полностью удовлетворенными, я заключаю, что именно здесь объектные базы данных сегодня наиболее заметно демонстрируют свои преимущества.
Крейг Рассел: Самым низким уровнем абстракции при использовании Java и SQL является вездесущая модель программирования JDBC. Она предоставляет лучший уровень управления и позволяет использовать все возможности драйвера и базы данных. Но ее также и труднее всего правильно понять, и она сама по себе не поддается абстрагированию.
Многие программисты полагают, что использование библиотек для реализации объединенных ресурсов позволяет улучшить производительность без потребности написания дополнительного кода, но для этого требуется хорошее понимание SQL. И обработка подготавливаемых операторов и результирующих наборов данных по-прежнему представляет проблему.
Более высокий уровень абстракции обнаруживается в инструментальных средствах типа iBATIS, которые во многом избавляют от рутинной работы с подготавливаемыми операторами и результирующими наборами данных, но для которых по-прежнему требуется написание конструкций SQL, сильно зависящих от особенностей СУБД. Кроме того, по-прежнему требуется дополнительная работа для использования отображенных на базу данных прикладных объектов.
Наиболее высокий уровень инструментария, известный мне в мире Java, обнаруживается в решениях объектно-реляционного отображения, таких как Enterprise Java Beans Container Managed Persistence, JPOX, OpenJPA, Hibernate, TopLink и Cayenne. Java Persistence API и JDO – это стандарты JCP, которые реализуются во многих из этих решений. У этих инструментальных средств имеется достаточно высокий уровень автоматизации, и они позволяют как создавать прикладные классы Java на основе схемы базы данных, так и создавать схему базы данных на основе прикладных объектов Java.
Вне мира Java развитыми функциональными возможностями обладают инструментальные средства Grails и Ruby on Rails. Кроме того, на их основе реализованы каркасы Web-серверов, позволяющие программистам избежать скучного ручного кодирования взаимодействия с базами данных.
Вопрос 3: Каково ваше мнение о достоинствах и недостатках имеющихся решений?
Майк Кейт: Ответу на этот вопрос можно посвятить целую книгу, можно бесконечно рассуждать о том, когда и где следует использовать то или иное решение. Если говорить коротко, то я полагаю, что все решения имеют право на существование, и нет какого-то одного решения, которое было бы наилучшим выбором для всех приложений. Можно надеяться только на то, что люди немного подумают, прежде чем выбирать решение, для поддержки которого они собираются затратить до 30% ресурсов своего приложения.
Тед Ньюард: Здесь требуется очень длинный ответ, несомненно, более сложный, чем я могу предоставить сейчас.
Карл Розенбергер: Одно из ключевых преимуществ объектно-ориентированной практики состоит в том, что сокращается стоимость долговременного сопровождения приложений. При использовании объектной базы данных это преимущество распространяется на модель данных (классы и прочее) и на весь код, взаимодействующий с базой данных.
При использовании объектной базы данных весь код приложения может быть написан на одном языке программирования. Рефакторинг может быть полностью автоматизирован с использованием современных IDE.
Объектные базы данных позволяют проверять во время компиляции 100% кода приложений, включая весь код, предназначенный для взаимодействия с базой данных.
Поскольку объектные базы данных могут обращаться со ссылками на объекты точно так же, как работает с ними виртуальная машина в основной памяти (используя однонаправленные указатели, не индексированные кортежи), объектные базы данных могут быть гораздо более быстрыми, чем реляционные базы данных.
Встраиваемые объектные базы данных, разработанные в расчете на конкретную программную среду и выполняемые в той же виртуальной машине, что и приложение, позволяют производить профилирование и настройку узких мест приложения глубоко внутри базы данных. Это делает объектные базы данных идеальным выбором для встроенного использования в мобильных телефонах и карманных компьютерах, обладающих ограниченными ресурсами процессора и памяти.
Язык SQL широко распространен. Зрелые SQL-ориентированные СУБД обладают долгой историей, и имеется много зрелых инструментальных средств, помогающих создавать, настраивать и запрашивать SQL-ориентированные системы.
SQL – это приемлемый стандарт для формулировки непредвиденных запросов к базам данных и непредусмотренной заранее агрегации данных.
Крейг Рассел: Вообще говоря, чем выше используемый уровень абстракции, тем быстрее создаются и внедряются приложения.
Но для получения последних крох производительности системы баз данных в некоторых приложениях требуется прямое использование SQL.
Поэтому нельзя обойтись без глубокого понимания конкретного диалекта SQL, на котором основывается используемая СУБД. Но почти все инструментальные средства позволяют выполнить большую часть работы на высоком уровне абстракции, требуя погружения в SQL только в крайних случаях.
Вопрос 4: Считаете ли вы, что средства объектно-реляционного отображения являются пригодным решением проблемы «персистентности объектов»? Если да, то почему? Если нет, то почему?
Майк Кейт: Технология объектно-реляционного отображения – это просто и реальность, и необходимая потребность в мире, в котором подавляющее большинство корпоративных данных сохраняется в реляционных базах данных, а парадигмы объектно-ориентированного программирования становятся нормой для разработки приложений. При наличии этой реальности вопрос в действительности состоит не в том, как решать проблему персистентности объектов, а в том, как решить проблему, существующую в 97% сценариев разработки приложений, когда приложение пишется на языке Java и должно выбирать и сохранять данные в реляционной базе данных. До сих пор объектно-реляционное отображение является наиболее гибким и практичным решением этой проблемы. Является ли оно достаточным? Безусловно, да, для множества разработчиков, успешно его использующих. Всегда ли оно является наилучшим решением? Я почти уверен, что если спросить об этом достаточное число людей, то среди них найдутся такие, которые ответят на этот вопрос отрицательно.
Тед Ньюард: Я думаю, что эта технология работает на тех разработчиков, которые готовы ставить производительность труда и простоту разработки выше эффективности и реляционной понятности базы данных. Эффективность базы данных или наличие добротной и понятной модели данных достигаются не так легко, как думают разработчики, и обычно понимание этого приходит слишком поздно, чтобы можно было заменить объектно-реляционное отображение чем-нибудь более «реляционно-дружественным» без существенного рефакторинга и переписывания кода.
Карл Розенбергер: Применение средств объектно-реляционного отображения – это временное решение. До некоторой степени они помогают сократить объем работы по написанию кода SQL вручную.
Но никакие временные решения не даются бесплатно. Вот несколько областей, в которых средства объектно-реляционного отображения далеки от идеала:
• Эффективность
Инструментальные средства объектно-реляционного отображения замедляют приложения. Для выполнения объектно-ориентированной бизнес-логики объекты приходится полностью загружать в память.
• Сложность
Средства объектно-реляционного отображения вводят собственные побочные эффекты из-за применяемых в них способов кэширования и переноса объектов. Разработчики теряют время на понимание того, как применяемое ими средство объектно-реляционного отображения ведет себя в сценариях параллельной работы с базами данных.
• Ограничения разработки
Никакое инструментальное средство объектно-реляционного отображения не может иметь дело со всеми допустимыми конструкциями языка программирования просто по той причине, что не для всех конструкций имеются эквиваленты в реляционном мире. При разработке прикладной модели классов, хорошо работающей при использовании средства объектно-реляционного отображения, всегда придется прибегать к компромиссам.
Временные решения никогда не устраняют проблемы. Они обеспечивают всего лишь промежуточный шаг на пути поиска истинного решения.
Крейг Рассел: Для многих приложений объектно-реляционное отображение является совершенно замечательным средством, позволяющим сбалансировать потребности разработчика с требованиями управления ресурсом центра данных, в котором хранится база данных. Очевидно, что именно там схема базы данных тщательно контролируется и управляется. В другом крайнем случае, когда схема базы данных контролируется программистом приложения путем написания классов Java и генерации на их основе схемы, большой опасностью является то, что приложение будет работать не слишком хорошо, может оказаться трудно переработать классы прикладной области для генерации правильной схемы, и даже после этого останется проблема миграции данных.
Вопрос 5: Считаете ли вы, что системы реляционных баз данных являются пригодным решением проблемы «персистентности объектов»? Если да, то почему? Если нет, то почему?
Майк Кейт: И вновь реляционные базы данных обычно не предоставляют ответ, они вынуждают задавать новый вопрос. Во всех случаях, когда приложение не разрабатывается с нуля в некоторой новой брендовой компании, имеются шансы, что приложению придется пользоваться данными из реляционной базы данных. На самом деле, и разработчики большинства новых брендовых приложений обращаются к технологии реляционных баз данных для хранения данных, поскольку эта технология является зрелой, масштабируемой и надежной. Вопрос состоит в том, как осуществлять доступ к этой реляционной базе данных, когда бизнес-логика программируется на объектно-ориентированном языке, например, на Java?
Тед Ньюард: Я думаю, что независимо от того, пригодны или не пригодны реляционные базы данных для решения проблемы персистентности объектов, в современной IT-инфраструктуре по ряду причин предполагается и требуется хранить данные в реляционной базе данных, и разработчикам нужно находить способы вкладывать свои объекты в эти данные. Однако часто не требуется делать это напрямую из пользовательского интерфейса, и применение промежуточной объектной базы данных, которая обновляет реляционное хранилище в пакетном или периодическом режиме, может существенно повысить производительность труда разработчиков.
Карл Розенбергер: Нет. Потеря соответствия является проблемой, а не решением.
Крейг Рассел: В связке с любыми средствами отображения Java на базу данных, да.
Вопрос 6: Считаете ли вы, что системы объектных баз данных являются пригодным решением проблемы «персистентности объектов»? Если да, то почему? Если нет, то почему?
Майк Кейт: Объектные базы данных похожи на betamax 20-го столетия. Они хорошо справлялись с одним делом, но не стали популярными. Они стали обособленными, не потому, что были ужасными, трудно используемыми или медленными, хотя отчасти и поэтому тоже, но из-за того, что не обслуживали разнородные приложения, требуемые компаниям. Хотя в IT-приложениях постоянно изменяются как функциональные возможности, так и используемые технологии, данные, с которыми они работают, остаются в основном теми же. Данные должны быть легко доступными из всех технологий и приложений. Этому требованию отвечали реляционные базы данных, а объектные базы данных удовлетворяли его не слишком хорошо.
Тед Ньюард: Безусловно, объектные базы данных пригодны для решения этой проблемы, если не требуется обеспечивать доступ к данным, хранимым в объектной базе данных, для необъектных технологий. Это остается крупнейшим недостатком ООСУБД.
Карл Розенбергер: Конечно, пригодны. Для объектных баз данных этой проблемы нет. При использовании объектной базы данных можно сохранить любой объект с помощью одной строки кода. Отсутствует потребность в дополнительной работе по поддержанию таблиц и отображений. Средства запросов являются неотъемлемой частью языка программирования. Как и все другие части приложений, код, взаимодействующий с базой данных, типизирован, проверяется на этапе компиляции и пригоден для выполнения автоматического рефакторинга.
Крейг Рассел: Рынок объектных баз данных в большей степени имеет отношение к прикладным областям, чем к программным моделям, используемым для доступа к базам данных. Мотивацией объектных баз данных во многом является эффективность системы при наличии конкретных моделей прикладной области и характеристик нагрузки. Для особо требовательных приложений эффективность объектных баз данных может на порядки превосходить эффективность реляционных систем. В этих случаях проблемой становятся средства запросов и генерации отчетов, распространение событий, синхронизация с другими базами данных и отказоустойчивое функционирование.
Вопрос 7: Какие исследования и разработки в области персистентности объектов вы считали бы уместными в следующие 12 месяцев?
Майк Кейт: Поразительно, как долго могут существовать данные. Одной из проблем долговечности данных является то, что проприетарные схемы хранения, многие из которых появились до того, как стали популярными реляционные базы данных, по-прежнему должны использоваться для доступа к данным. Спросите системных интеграторов, с чем им приходится иметь дело, и вы втянетесь в гораздо более долгое обсуждение, чем рассчитывали.
Кроме того, повсеместно распространенным становится XML как глобальный язык данных, и оказывается, что сервис-ориентированные объекты приходится регулярно преобразовывать в XML и реляционные записи, а также и в записи унаследованных проприетарных хранилищ данных. В исследованиях следующего года (или позже) эта проблема должна быть решена способом, удовлетворяющим разработчиков на каждом шаге процесса разработки. По-видимому, должно использоваться не одно общее решение проблемы персистентности объектов, а некоторый набор единообразных решений, являющихся согласованными, интегрированными и обеспечивающими на каждом уровне то, что требуется.
Тед Ньюард: Интеграция в языки программирования понятий реляицонной модели данных и теории множеств.
Карл Розенбергер:
(1) Слияние объектно-ориентированных и функциональных языков.
Мне нравятся функциональные языки программирования, поскольку в них поддерживаются мощные понятия, позволяющие работать с множествами с использованием списочных включений (list comprehension). Кроме того, я считаю, что объекты обеспечивают наилучший способ представления состояния.
Я вижу блестящее будущее языков программирования в слиянии функциональных понятий и объектной ориентированности. Проекты Scala и LINQ являются крупными шагами в правильном направлении.
Для анализа списочных включений и их выполнения над индексами базы данных не требуется сложная умственная деятельность. На понятийном уровне это похоже на механизм Native Queries в db4o. Я надеюсь, что мы попробуем сделать это с использованием списочных включений языка Scala … если мы это не сделаем, то я уверен, что это сделает кто-нибудь еще из нашего сообщества.
(2) Новые понятия параллелизма.
Тенденция к переходу к многоядерным процессорам вынуждает включать в языки программирования новые концепции для управления параллелизмом.
Двумя отличными подходами, которые могут быть внедрены в распространенные языки программирования, являются программная транзакционная память (Software Transactional Memory) и акторы (Actor). Оба подхода заслуживают того, чтобы подумать, как их можно лучше всего использовать при работе с базами данных.
(3) Управление состоянием
В объектно-ориентированном мире имеется состояние в клиентах и в распределенных системах: объекты.
Поразительно мало исследований посвящается той проблеме, как поддерживать синхронизацию состояния объектов в клиентах с зафиксированным состоянием объектов на сервере. В реляционных базах данных поддерживаются изолированное чтение и блокировки, но это не решает реальную проблему. Они работают так, как если бы не было состояния объектов в клиентах. Это еще одна проблема потери соответствия.
Я не верю в блокировки в параллельном мире.
Я думаю, что к решению этой проблемы лучше подходить, либо проталкивая изменения в клиентов, либо работая с версиями объектов, являющимися согласованными к некоторому моменту времени.
Было бы очень интересно опытным путем опробовать оба эти подхода для определения того, в каких случаях один из них работает лучше другого.
Крейг Рассел: Cлабыми местами персистентности объектов остаются инструментарий и генерация приложений, в особенности, интеграция со средствами генерации интерфейсного скриптового кода.
Вопрос 8: Если бы вы могли влиять на принятие технологических решений в последние 10 лет, какое бы из них использовалось в типичном сегодняшнем проекте в качестве механизма поддержки персистентности и почему?
Майк Кейт: Для начала я отказался бы от EJB в пользу модели POJO и избавил бы мир от восьмилетней головной боли. Я также заставил бы все это работать со Smalltalk. 😉
Тед Ньюард: Я бы никогда не навязывал решение для какого-либо проекта. «От каждой технологии сообразно ее возможностям для каждого проекта сообразно его потребностям.»
Карл Розенбергер: Давайте смотреть в будущее, а не в прошлое. Работая на db4objects, я надеюсь, что смогу как-то повлиять на следующие 10 лет. В сегодняшних новых проектах, относящихся к мобильным телефонам и устройствам, следует использовать технологию объектных баз данных, если это уже не делается.
Я не являюсь экспертом в области крупномасштабных корпоративных баз данных, но я сомневаюсь, что базы данных в grid близки к той эффективности, которой они могли бы обладать. Поскольку большая часть кода сегодняшних зрелых крупномасштабных серверов баз данных написана на языках C или C++, и поскольку в этих языках не поддерживаются высокоуровневые понятия распределенности и параллельности, я полагаю, что сопровождение и совершенствование этих систем должны быть очень утомительны и неэффективны.
Вероятно, несколько умных людей могут за счет осмысленных усилий создать очень быструю огромную распределенную базу данных, которая очень быстро окупится. Если бы я был всесилен, я бы хотел предпринять попытку выполнения такого проекта. Но, возможно, имеет смысл подождать, пока новые концепции параллелизма станут немного более зрелыми.
В отношениях не определяется следующее:
• где начинается и заканчивается согласованность;
• кто владеет главной копией каждого кортежа;
• как данные должны быть распределены в кластере;
• когда имеет смысл упреждающее чтение;
• как данные физически кластеризуются.
В основном я отдаю предпочтение понятиям, которые наполнены знаниями, присутствующими в языках программирования, и передают эти знания в область баз данных. С теоретической точки зрения принятие технологии объектных баз данных могло бы иметь смысл даже для корпоративных баз данных, если бы все корпоративные приложения, обращающиеся к базе данных, писались на совместимых объектно-ориентированных языках. В идеале имелась бы общая объектно-ориентированная модель предметной области, которую можно было бы совместно использовать для всех корпоративных приложений во всем мире.
На самом деле, я думал об этом больше десяти лет тому назад. Если бы я был всемогущим, сегодня все бы пользовались такой моделью … и тогда никто бы не сомневался, что объектная база является наиболее естественным решением проблемы персистентности для всех приложений.
Крейг Рассел: В типичном сегодняшнем проекте использовалась бы первоклассная среда IDE совместно с подключаемыми модулями для поддержки уровня персистентности объектов. Эти модули могли бы опираться на реляционные или объектные базы данных для хранения объектов.
Среда IDE могла бы генерировать полный код каркаса Web-серверов, включая артефакты JavaScript для поддержки интерактивного рендеринга и пользовательского интерефейса.
В виртуальной машине Java допускалась бы общая поддержка классов для отслеживания изменений и избежания зависящего от поставщиков преобразования байт-кода. Инструментальные средства поддержки времени исполнения динамически настраивали бы приложения без вмешательства человека.
Вопрос 9: Можете ли вы сказать что-нибудь еще на эту тему?
Возможно, это связано с тем, что персистентность оказывает серьезное влияние на эффективность приложений, а может быть, просто потому, что пересистентность настолько интересна, но после 18 лет исследований и разработок в области персистентности я по-прежнему чувствую, что на это стоит тратить время. По-видимому все согласятся с тем, что разработчики, не обращающие внимание на аспекты персистентности своих приложений, многим рискуют.
Спасибо за приглашение к участию в этой дискуссии.
Тед Ньюард: Спасибо за приглашение.
Карл Розенбергер: Я верю в бионику. Мы можем многое узнать из того, как проблемы решаются в природе. Взглянем, например, на то, как в природе организуются знания. Имеется множество медленных избыточных систем (людей), использующих постоянно совершенствующиеся эффективные методы коммуникации. Любой узел может общаться с любым другим узлом, и направление и сила связи может приспосабливаться для соответствия текущим потребностям. Если принять это в качестве модели, то будущим, в частности, баз данных является интеллектуальный grid-компьютинг, в котором будут происходить приспособление к текущим потребностям и обучение на ошибках.
И как это согласуется с описанной выше общей моделью предметной области?
Я думаю, очень хорошо. У людей имеется общая объектно-ориентированная модель предметной области, сравнительно стабильная во времени: естественный язык. Поскольку и раньше использовался естественный язык, мы можем читать и понимать тексты, написанные тысячи лет назад.
Нам очень повезло, что древнегреческие тексты не писались с использованием объектно-реляционного отображения. Эволюция – это медленный непрерывный процесс. В конце концов, побеждает наилучшая концепция.
Спасибо за приглашение к участию в дискуссии.
Крейг Рассел: Спасибо за приглашение.