Книга: Дефрагментация мозга. Софтостроение изнутри
ORM, или объектно-реляционный проектор
Сокрытие базы данных, или Как скрестить ежа с ужом
Упомянув один из крупнейших столпов современного софтостроения – мир ООП, нельзя обойти вниманием и другой – мир реляционных баз данных. Я намеренно вставил прилагательное «реляционные» применительно ко всем основным СУБД[45], хотя ещё в 1970-х годах такое обобщение было бы неправомерным.
Тем не менее именно реляционным СУБД удалось в 1980-х годах освободить программистов от знания ненужных деталей организации физического хранения данных, отгородиться от них структурами логического уровня и стандартизованным языком SQL[46] для доступа к информации. Также оказалось, что большинство форматов данных, которыми оперируют программы, хорошо ложатся на модель двумерных таблиц и связей между ними. Эти два фактора предопределили успех реляционных СУБД, а в качестве поощрительной премии сообщество получило строгую математическую теорию в основании технологии.
В отличие от реляционного мира, ООП развивалось инженерами-практиками достаточно стихийно, исходя из потребностей программистского сообщества, и потому никакой строгой теории под собой не имело. Имевшие место попытки подвести таковую под ООП задним числом терпели неудачу. Наилучшего результата добились авторы объявленного стандартом UML[47], который, однако, в основном до сих пор используется в качестве иллюстрирующих код картинок. Но лучше плохой стандарт, чем никакой.
И реляционная и объектная модели относятся к логическому уровню[48] проектирования программной системы. Они ортогональны и по сути представляют собой два взгляда на одну и ту же сущность. Это значит, что вы можете реализовать одну и ту же систему, оставаясь в рамках только одного реляционно-процедурного подхода или же следуя исключительно ООП.
На практике сложилась ситуация, когда программы пишутся в основном с использованием ООП, тогда как данные хранятся в реляционных БД. Не касаясь пока вопроса целесообразности такого скрещивания «ежа с ужом», примем ситуацию как данность, из которой следует необходимость отображения (проецирования) объектов на реляционные структуры и обратно.
Ввиду упомянутого отсутствия под ООП формальной теоретической базы эта задача, в общем случае нерешаемая, выполнима в случаях частных. Компонент программной системы, реализующий отображение, называется ORM[49], или объектно-реляционный проектор – ОРП. Полноценный ORM может быть весьма нетривиальным компонентом, по сложности превосходящим остальную систему. Поэтому, хотя многие разработчики с успехом пользуются своими собственными частными реализациями, в отрасли за последние 10 лет появилось несколько широко используемых фреймворков, выполняющих в том числе и задачу проекции.
Обзор средств объектно-реляционной проекции выходит за рамки данной книги. Их и так достаточно в Сети, включая небольшой мой собственный [8], сделанный ещё в 2005 году, но не сильно устаревший. Поэтому последующие примеры будут в основном касаться фреймворка NHibernate.
В технологии отображения объектов на РСУБД есть очень важный момент, от понимания которого во многом зависит успех вашего проекта. Я не раз слышал мнение программистов, что для слоя домена[50] генерируемый проектором SQL код является аналогом результата трансляции языка высокого уровня в ассемблер целевого процессора. Это мнение не просто глубоко ошибочно, оно быстрыми темпами ведёт команду к созданию трудносопровождаемых систем с врождёнными и практически неисправимыми проблемами производительности.
Проще говоря, как только вы подумали о SQL как о некоем ассемблере по отношению к используемому языку ООП, вы сразу влипаете в очень нехорошую историю.
SQL – высокоуровневый декларативный специализированный язык четвёртого поколения, в отличие от того же Java или C#, по-прежнему относящихся к третьему поколению языков императивных. Единственный оператор SQL на три десятка строк, выполняющий нечто посложнее выборки по ключу, потребует для достижения того же результата в разы, если не на порядок, больше строк на C#.
Такая ситуация приводит разработчиков ORM к необходимости создавать собственный SQL-подобный язык для манипуляции объектами и уже его транслировать в сиквел[51] (см. HQL[52]). Или использовать непосредственно SQL с динамическим преобразованием результата в коллекцию объектов.
В противном случае прикладной программист обречён на извлечение из БД и последующую обработку больших массивов данных непосредственно в своём приложении. Примерно так же обрабатывали табличные данные при отсутствии встроенного SQL разработчики на ранних версиях Clipper в конце 80-х годов. Там это называлось «навигационная обработка». Думаю, термин уместен и здесь.
В эпоху массового перехода с Clipper-подобных программ и файл-серверных технологий на клиент-серверные РСУБД многие приложения и их разработчики продолжали использовать навигационный подход. Приложения работали медленно, зачастую блокируя работу в многопользовательской среде. Потому что для эффективной работы с РСУБД нужно использовать подходы, ориентированные на обработку множеств на сервере, предполагающие наличие у разработчика умений работать с декларативными языками.
Тем не менее, получив в распоряжение ORM, программист зачастую возвращается к навигационным подходам обработки массивов данных вне РСУБД лишь с той разницей, что теперь этот массив, как хочется надеяться, является содержимым целой таблицы.
Почему? Недостаток знаний РСУБД пытаются возместить дополнительными уровнями абстракций. На деле же выходит обратное: уровни абстракции скрывают не детали слоя хранения объектов от программиста, а, наоборот, его некомпетентность в области баз данных от СУБД. До некоторого времени.
Несмотря на толстый слой абстракций, предоставляемый ORM типа Hibernate, заставить приложение эффективно работать с РСУБД без знаний соответствующих принципов ортогонального мира и языка SQL практически невозможно.
Но попытки продолжаются. Одни по-прежнему разрабатывают проекторы для своих внутренних нужд, зачастую очень лёгкие. Другие ищут упрощение и выход в noSQL[53]. Но в выигрыше пока остаются программисты и консультанты, обладающие «базоданными» компетенциями и зарабатывающие на тех, кто ими не обладает.
- 1.1. Введение в объектно-ориентированное программирование
- Information request
- SCTP Generic header format
- 2.3 Executable and Linking Format
- На всех дисках моего компьютера есть папка System Volume Information. Для чего она нужна?
- fdformat
- Convection Currents of Information
- Working with Graphics Formats
- Sound Formats
- Video Formats
- Common Configuration Information
- Configuring Apache for Peak Performance