[Moscow.pm] Размышления на тему ORM и вообще работы с БД
Naim Shafiev
shafiev на gmail.com
Ср Окт 26 10:03:01 PDT 2011
26 октября 2011 г. 21:26 пользователь Ivan Petrov
<i.petro.77.00 на gmail.com> написал:
> сделали мы тут цельный проект на DBIx::Class. С точки зрения
> попробовать последний. До этого всегда использовали DBI, который
> использовала модель в системе MVC.
>
> Впечатления плохие, однако появились мысли куда надо двигаться чтобы
> было хорошо. Я их тут изложу, а вы покритикуйте.
>
> В первую очередь зачем как бы нужен был этот DBIC.
> - конструирование SQL-запросов
> - уход от смешивания кода Perl с кодом SQL
> - выборка объектов, а не хешей из БД, которые можно расширять своими
> методами
> - упрощение кода моделей с точки зрения что в простых случаях вообще
> не делать выделенную модель
>
> Ничего не забыл?
>
> По результатам проекта (проект был довольно большой и дальше еще будет
> долго) я понял следующее:
>
> 1. даже в простых случаях DBIC на роль модели не годится. То есть в
> любом случае нужно делать выделенную модель, пусть даже там один
> resultset('Name')->find. Ибо тесты. При их написании мы применяем
> способ "подменить модель на стадии тестирования".
>
> 2. DBIC не предоставляет хорошей абстракции над БД. Все равно
> JOIN'ы, SELECT'ы торчат местами (например join_type => 'left' в has'ах
> итп). То есть оперировать хранилищем как некоей абстракцией в реальном
> случае не получается.
>
> 3. Конструктор SQL-запросов крайне страшен. Работали мы с постоянно
> включенной отладкой (выводом всех делающихся запросов в лог). С одной
> стороны есть множество вещей которые на DBIC сделать крайне непросто
> (например многие аггрегаторные вещи), с другой стороны когда
> начинается работа с более чем двумя таблицами он зачастую мутит такие
> страшные вложенные SQL-запросы что волосы дыбом становятся, а с
> третьей стороны использование фич конкретной БД становится затруднено.
>
> В итоге пришли к тому, что в сложных случаях приходится делать в БД
> view'ы только из за того что от DBIC добиться генерации нормального
> запроса очень и очень сложно или невозможно. Набор опций при выборке
> может быть больше самого SQL-запроса, если его просто написать.
>
> Ну вот и в свете того, что код работы с DBIC все равно располагается в
> моделях, конструировать эффективные SQL-запросы он все равно не умеет,
> то из плюсов его использования остаются только:
> - выборка в объекты и итераторы по ним
> - уход от смешивания Perl и SQL
>
> Соответственно размышляя над всем этим мы пришли к тому, что
>
> 1. построить качественный автогенератор SQL запросов на все случаи
> жизни (или по кр. мере на большинство) невозможно, поэтому его не
> стоит и пытаться сделать
>
> 2. из за п.1 бОльшая часть DBIC становится не нужна, а надо делать
> некоего помощника, который бы человеку просто помогал удобно работать
> с БД.
>
> то есть надо
>
> 1. написать свой итератор, работающий поверх массива или
> хеша - выборки из БД.
> 2. написать базовую обертку над одной строкой выборки (доступ в виде
> методов)
> 3. Используя 1 и 2 написать над DBI класс, который выборки блессает в
> итераторы и объекты
> 4. решить вопрос с выносом SQL-кода из перловых модулей. То есть
> обертка 3 должна уметь работать с SQL, располагающимися в файлах.
>
>
> Вынос SQL в файлы очень плохо соотносится с дефолтными плейсхолдерами
> DBI. поскольку они позиционные.
>
> Вывод:
> 5. надо реализовывать именованные плейсхолдеры
>
> ну и попутно
> 5.1 реализовать плейсхолдерные (темплейтные) выражения для типовых
> вещей, как-то
> INSERT ... VALUES (?,?,?),(?,?,?),(?,?,?),...
>
> или
> SELECT ... WHERE id IN (?,?,?)
>
> то есть подстановки массивов.
>
> Соответственно исходя из этого родился набор модулей, который в
> ближайшее время, если кому-то будет интересно, мы можем выложить на
> CPAN (там еще работы на неск. дней осталось), который все это делает:
>
> 1. по дефолту блесает строки-выборки в объект, у которого три
> предопределенных метода: new, is_changed, iterator. Плюс методы
> совпадающие с именами выбранных столбиков.
>
> 2. блесает наборы-выборки в объект позволяющий делать проходы по
> выборкам итп (совместимо с DBIC'шными ->all, while(...->next) итп
>
> 3. в п. 1 и 2 позволяет указывать свои классы для итераторов и выборок
>
> 4. позволяет вместо SQL использовать имена файлов SQL в предзаданной
> директории (по аналогии с темлейтами любого вебпроекта)
>
> 5. реализует следующий набор подстановок в SQL
>
> ?{путь} - просто подставляет переменную
> ?@{путь} - подставляет массив переменных (через запятую)
> ?%{путь}{поле,поле,...} - подставляет массив переменных (через
> запятую) из массива хешей
>
> ну и на вс случай сделали
> ?sub{перловый код}
>
>
> А так же набор условных подстановок вроде
>
> ?if[de]?{путь}{ блок который вставится }{else-блок}
>
> условия - if - истина
> ifd - определен
> ife - имеется
>
> Блоки можно вкладывать друг в друга.
>
> пути - по сути путь к переменной во входном хеше, то есть
>
> $dbh->do($sql, values => { ids => [1, 3, 5] }, abc => 'def');
>
> путями являются
> 'values'
> 'abc'
> 'values.ids'
>
> и так далее.
>
> поддерживаются в путях и объекты
>
> path.to:method - будет вызван метод объекта, а значение им
> возвращенное будет вставлено в SQL.
>
>
> В итоге что получили:
>
> 1. SQL вынесен в отдельный каталог (отдельные каталоги) примерно так
> же как вынесены темплейты в любом вебпроекте
> 2. типичные SQL-вещи делаются просто. Сложные тоже можно делать.
> 3. Поскольку итератор по именам методов постарались сделать
> совместимым с DBIC то замена одного на другое не вызывает больших
> трудностей.
>
> ну и возьмем пример:
>
> скажем приходит от пользователя форма
>
> $filters = { region => 'Москва', street => '' };
>
> То есть он фильтр по региону заполнил, а фильтр по улице нет
>
> запрос может выглядеть так
>
> SELECT
> *
> FROM
> tbl1
> LEFT JOIN tbl2 ...
>
> WHERE
> something = ..
>
> ?if{filters.region}{ AND region = ?{filters.region} }
> ?if{filters.street}{ AND street = ?{filters.street} }
>
> и так далее.
>
> Получается SQL перестраивается в зависимости от того что там вводит
> пользователь.
>
> Осталось нерешенными некоторые типовые вопросы, но мы их планируем
> порешать в ближайшее время (например подставновки частей в
> like-секции)
>
> соответственно вопросы:
>
> 1. кому-нибудь интересна подобная система, стоит класть на CPAN?
Безусловно стоит.При множестве глаз баги выплывают на поверхность
> 2. может на эту тему есть что-то готовое да мы велик очередной ваяем?
> тогда ткните указкой:)
> --
> Moscow.pm mailing list
> moscow-pm на pm.org | http://moscow.pm.org
>
Подробная информация о списке рассылки Moscow-pm