[Moscow.pm] Размышления на тему ORM и вообще работы с БД

Yury Pats yu.pats на gmail.com
Ср Окт 26 10:13:49 PDT 2011


2011/10/26 Andrei <andrei.protasovitski на gmail.com>:
> И как у этого велосипеда с производительностью на больших объёмах данных?
>
Расскажи лучше нам про велосипед из патченного CDBI :)

Но вопрос задан правильно. Универсальное решение не будет шустро
работать при полноценном использовании его универсальности.


>> соответственно вопросы:
>>
>> 1. кому-нибудь интересна подобная система, стоит класть на CPAN?
Выкладывайте хотя бы на гитхаб!


> 26 октября 2011 г. 18: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
>
>
>
> --
> Andrei Protasovitski
> < andrei[dot]protasovitski[at]gmail[dot]com >
> Diemen, Netherlands
>
> --
> Moscow.pm mailing list
> moscow-pm на pm.org | http://moscow.pm.org
>
>



-- 
WBR, Yury Pats
skype: yuripats
cellular: +375 (29) 5870723


Подробная информация о списке рассылки Moscow-pm