[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