KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программы » Сергей Тарасов - Дефрагментация мозга. Софтостроение изнутри

Сергей Тарасов - Дефрагментация мозга. Софтостроение изнутри

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Сергей Тарасов, "Дефрагментация мозга. Софтостроение изнутри" бесплатно, без регистрации.
Перейти на страницу:

Осталось решить небольшую организационную задачу: где в некритичном проекте автоматизации «отдела Х» найти бюджет на компетентного системного аналитика, технического архитектора и ведение хотя бы минимального набора проектной документации.

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]. Но в выигрыше пока остаются программисты и консультанты, обладающие «базоданными» компетенциями и зарабатывающие на тех, кто ими не обладает.

Как обычно используют ORM

На софтостроительных презентациях часто рисуют красивые схемы по разделению слоёв представления, бизнес-логики и хранимых данных. Голубая мечта начинающего программиста – использовать только одну среду и язык для разработки всех слоёв и забыть про необходимость знаний реляционных СУБД, сведя их назначение к некоей «интеллектуальной файловой системе». Аббревиатура SQL вызывает негативные ассоциации, связанные с чем-то древним, не говоря уже про триггеры или хранимые процедуры. На горизонте появляются добрые люди, с книгами признанных гуру о домен-ориентированной разработке[54] под мышкой, заявляющие новичкам примерно следующее: «Ребята, реляционные СУБД – пережиток затянувшейся эпохи 30-летней давности. Сейчас всё строится на ООП. И есть чудесная штука – ORM. Начните использовать её и забудьте про тяжёлое наследие прошлого!»

Ребята принимают предложение. Дальше эволюция разработки системы примерно следующая:

• Вначале происходит выбор ORM-фреймворка для отображения. Уже на этом этапе выясняется, что с теорией и стандартами дело обстоит плохо. Впору насторожиться бы, но презентация, показывающая, как за 10 минут создать основу приложения типа записной книжки контактов, очаровывает. Решено!

• Начинаем реализовывать модель предметной области. Добавляем классы, свойства, связи. Генерируем структуру базы данных или подключаемся к существующей. Строим интерфейс управления объектами типа CRUD[55]. Все достаточно просто и на первый взгляд кажется вполне сравнимым с манипуляциями над DataSet[56] – тем, кто о них знает, конечно – ведь не все подозревают о существовании табличных форм жизни данных в приложении за пределами сеток отображения DBGrid.


Как только разработчики реализовали CRUD-логику, начинается основное действо. Использовать сиквел напрямую теперь затруднительно. Если не касаться стратегий отображения и проблем переносимости приложения между СУБД, по сути каждый SQL-запрос с соединениями, поднявшись в домен, сопровождается специфической проекцией табличного результата на созданный по этому случаю класс. По этой причине приходится использовать собственный язык запросов ORM. Нестандартный, без средств отладки и профилирования. Если он, язык, вообще имеется в данном ORM. Для поддерживающих соответствующую интеграцию среда. NET предоставляет возможность использовать LINQ[57], позволяющий отловить некоторые ошибки на стадии компиляции.

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*