среда, 28 января 2009 г.

Мой первый тренинг в качестве MCT

Легкий оффтоп.

Сегодня закончился мой первый тренинг в качестве сертифицированного тренера Microsoft.

IMG_4536 IMG_4537

Группа была не слишком многочисленная, но бодрая - держали меня в тонусе и постоянно задавали вопросы "вширь и вглубь". Отчасти именно из-за моего неумения вовремя остановить свои пояснения приходилось жертвовать практикой, отдавая ее на откуп самостоятельной (считай домашней) работе.

На собственном опыте убедился, что подобный тренинг и преподавание в ВУЗе - это далеко не одно и тоже. Во-первых трениг проходит интенсивнее, чем обычные занятия, во-вторых очень здорово помогает наличие учебных материалов. Ну и кроме того, методика подачи материала совсем другая, нет разделения на лекции/практику, тут "все в одном": рассказал - показал. В общем - новый опыт.

Надеюсь первый блин все-таки не вышел комом.

понедельник, 5 января 2009 г.

Организация доступа к данным: как сделать шоколадно-конфетное приложение

Дано: база данных, разработчик. Разработчик разрабатывает приложение. Приложение работает с данными, хранящимися в ... базе данных - отображает, редактирует, сохраняет.

Цель: разработчик хочет сделать из приложения "конфетку" - чтобы и хорошо, и красиво, и производительно, и чтобы много пользователей, и умеренные требования к "железу".

Сразу ограничу область "приложения" - не слишком большое (не больше 2х - 3х слоев, ибо бизнес-логика присутствует), но и не слишком маленькое (т.е. о масштабировании думать уже нужно, и вариант "меня спасут помощники в Visual Studio" не пройдет). Также договоримся, что большая часть тех данных, с которыми работает приложение хранится именно в реляционной СУБД - т.е. для доступа к ним используется SQL (в той или иной форме).

Несколько лет назад (5-6) в подобных случаях советовалось не хранить SQL в коде приложения, а выносить его в хранимые процедуры. Отлично. Результатом применения такого подхода является умопомрачительное количество этих самых процедур - по одной накаждую из CRUD -операций плюс еще что-то на бизнес-логику и логику отображения данных (как раз сейчас работаю с одним legacy приложением, в котором на 130 таблиц более 550 хранмых процедур). Такое положение дел не очень хорошо по целому ряду причин:

  • сложно поддерживать
  • сложно расширять
  • сложно обновлять
  • по производительности тривиальные хранимые процедуры, реализующие CRUD-операции, хуже динамически сгенерированного SQL-кода (особенно это касается операций обновления данных)

Новое время дает нам новые инструменты. На замену хранимым процедурам пришли ORM-библиотеки. Вроде бы все стало хорошо, мило и приятно - теперь уже можно вообще не писать SQL код. Но не все так просто. Да, с CRUD-операциями ORM справляется хорошо, но вот бизнес-логика зачастую вполне ощутимо "подтормаживает", т.к. требует извлечения довольно большого количества сущностей из БД. Если мы хотим создать приложение, которое будет "быдро пошевеливаться", то полностью отказываться от хранимых процедур нам нельзя - проверку сложной бизнес-логики, работающей на множестве объектов, из которых состоит/которыми оперирует наша система, лучше держать поближе к хранилищу этих объектов, т.е. в БД.

Но и тут наша история еще не заканчивается. Если взглянуть на типичное современное (веб-)приложение, то половина (если не больше) его функциональности - это отображение различных списков. Причем чаще всего эти списки имеют похожую функциональность:

  1. необходимо обеспечить сортировку по широкому спектру атрибутов (что делает невозможным применение хранимых процедур для получения данных)
  2. отображаемые данных "собираются" из нескольких сущностей (что ставит под сомнение эффективность применения ORM)
  3. необходимо обеспечить разбивку на страницы (что вкупе с первыми двумя пунктами "напрягает" и хранимые процедуры и ORM-средства)
  4. наличие функциональности по фильтрации данных (так что либо мы изощренно издеваемся над ORM, генерирую хитрые условия, либо динамически генерируем SQL-код в хранимых процедурах)
  5. в большинстве случаев данные, отображаемые в списке, не нужно редактировать (для этого есть отдельная страница)

По моему опыту, именно такие запросы сильнее всего загружают сервер баз данных. Можно, конечно, решить все перечисленные выше проблемы "методом лома" - грубой силой заставив выбранную технологию (хранимые процедуры или ORM) делать то, что требуется. Но тогда наверняка пострадает гибкость и производительность решения. А мы хотим "конфетку". В итоге мы приходим к необходимости еще одного нишевого решения - динамической генерации SQL для отображения списков (list view). Положительный эффект на уровне БД при этом может достигать 50 - 60% (по сравнению с вариантом "в лоб").

Итак, с моей точки зрения, сбаллансированный подход к организации доступа к данных (СУБД) заключается в следующем:

  • слой бизнес-логики (aka domain model) с применением ORM
  • бизнес-логика проверяется на сервере БД и (по крайнем мере часть ее) материализуется в виде хранимых процедур
  • для отображения списков используется динамическая генерация SQL-кода, которая позволяет получить эффективный (SQL-)код и уменьшить нагрузку на сервер БД