Какие запросы мешают вам использовать ORM?

Sad Spirit

мизантроп (Старожил PHPClub)
Команда форума
Ну вот, все желающие по мне оттоптались? Тогда развиваем мысль дальше.

Можно запостить сюда схему реляционной БД, все посмотрят и согласятся: ага, 3-я нормальная форма. Кто не согласится, тому можно привести определение 3НФ и строго доказать, что это таки она. Можно сказать, как привести схему в 4НФ.

А можно запостить сюда ОО код... И что потом обсуждать? "Запахи кода" (tm)? Ну так для вас ORM псевдокод пахнет фиалками, а для меня --- вовсе даже говном.

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

Андрейка

Senior pomidor developer
попробуй еще раз прочитать мою просьбу, ибо она начинается не с процитированного текста.
из кода
PHP:
// город имеет имя Барселона 
$city_filter = ORMFilterEquality('title', 'Барселона'); 

// (на точке есть ужин) И (точка находится в городе) 
$waypoint_filter = ORMFilterCompositeAND(); 
$waypoint_filter->add_filter(new ORMFilterBoundObject("Supper", new ORMFilterTrue())); 
$waypoint_filter->add_filter(new ORMFilterBoundObject("City", $city_filter)); 

// у компании есть остановка на маршруте (Waypoint) 
$company_filter = ORMFilterBoundObject("Waypoint", $waypoint_filter);
я лично вообще не понимаю (вопрос читабельности оставим на отдельный разбор) даже связей (между таблицами).. твоя псевдоORM сама с ними разбирается? или работает по скану куска туалетной бумаги с UML?
PS. це таки замаскированный объект "запрос к базе данных"
 

StUV

Rotaredom
bkonst
т.е. ты держишь в голове пересвязки между сущностями и вписываешь их в виде приватных действий в рамках твоей orm-либы - соответственно, для левого разработчика код становится совершенно непрозрачен и все эти движения выглядят как некие магические действия великого гуру, приводящие (к всеобщему изумлению зрителей) к нужному результату - так ?
 

bkonst

.. хочется странного?...
StUV
т.е. ты держишь в голове пересвязки между сущностями и вписываешь их в виде приватных действий в рамках твоей orm-либы - соответственно, для левого разработчика код становится совершенно непрозрачен и все эти движения выглядят как некие магические действия великого гуру, приводящие (к всеобщему изумлению зрителей) к нужному результату - так ?
Нет. Пересвязки между сущностями не входят в ORM-либу; они задаются в описании модели, которое является частью конкретного приложения.

Автор оригинала: Sad Spirit
Ну вот, все желающие по мне оттоптались? Тогда развиваем мысль дальше.

Можно запостить сюда схему реляционной БД, все посмотрят и согласятся: ага, 3-я нормальная форма. Кто не согласится, тому можно привести определение 3НФ и строго доказать, что это таки она. Можно сказать, как привести схему в 4НФ.

А можно запостить сюда ОО код... И что потом обсуждать? "Запахи кода" (tm)? Ну так для вас ORM псевдокод пахнет фиалками, а для меня --- вовсе даже говном.
Тю, ё-мое. Или издевается, или не понимает. Сравнил, понимаешь, схему данных с кодом (попу с пальцем)

Ок. Если есть алгоритм приведения модели в 3НФ (а он есть), почему этим должен заниматься человек?
Описал сущности и связи - получил 3НФ. Это автоматизируемо, ООП/ORM здесь не мешает. Еще вопросы есть?

ООП щас на хорошем ремесленном уровне, до научного пока не дотягивает
ООП, как вы могли бы заметить, понятие растяжимое. Если ограничиться тем, что можно сравнивать с РСУБД - а именно моделью/ORM, то "объектная" модель в реляционную и обратно преобразуются с помощью примитивнейшего алгоритма.

Андрейка
я лично вообще не понимаю (вопрос читабельности оставим на отдельный разбор) даже связей (между таблицами).. твоя псевдоORM сама с ними разбирается? или работает по скану куска туалетной бумаги с UML?
Вот тебе немножко сокращенное описание сущности:

PHP:
class TouristMetaclassRoute extends ORMMetaclass {
  function TouristMetaclassRoute() {
    $this->ORMMetaclass();

    $this->set_class_name('Route');

    // Здесь мы определяем связи
    $this->belongs_to('Country');
    $this->belongs_to('Company');
    $this->has_many('Waypoint');
  }
}

ORMMetaclass::_register(new TouristMetaclassRoute());
А разбирать модель заметно проще по рисунку (даже на туалетной бумаге, если он соответствует реальному положению дел), нежели по запросу.

PS. це таки замаскированный объект "запрос к базе данных"
(немного саркастично) ну кто бы мог подумать, что при поиске объектов, подходящих под заданные критерии, мы будем обращаться к хранилищу данных..

Это абсолютно НЕзамаскированный объект "запрос к базе данных".
 

whirlwind

TDD infected, paranoid
>т.е. ты держишь в голове пересвязки между сущностями

Нет. Они являются частью объекта. Мы говорим - объект А содержит атрибут, который ссылается на объект Б. Можно так же сказать - объект А содержит объект Б. Это то же самое что и FK. Только в SQL-запросе нужно явно указывать что с чем связано, если это не NATURAL, при котором нужно сделить за именованием колонок. В ORM это делается автоматически. И попробуйте доказать мне, что явное связывание в SQL-запросе двух таблиц, в одной из который _только_один_ FK_ на связываемую таблицу (а это наиболее частый случай) джойном является необходимостью и не может быть решен программным путем. А если вы хотите связывать не по FK/PK, то это уже проблема проектирования БД и никакого отношения к ORM она не имеет. Вы посмотрите на постановку вопроса

найти все компании, которые возят народ с ночевкой в барселоне (у кого-то там отель и он хочет продавать места в отеле оптом именно этим компаниям)
Нет здесь ничего о том что нужно де связать такую то сущность с такой-то. Меньше лишнего при использовании ORM. Это приближает запись к реально поставленной задаче, а не к раскрытию связей или деталей запроса. Неужели не понятно?
 

fisher

накатила суть
>>объекты и взаимосвязи между ними легко описываются
>>реляционной алгеброй
вот имхо здесь вы в корне не правы, но я согласен, что это частично флейм. я кстати думаю что Spirit тут мог бы внести ясность, но он че-то сам тоже отмалчивается. так вот. берем всякие там операции над множествами добавили логику предикатов и получаем сново множество, которое снова может быть операндом. это реляционная алгебра.
но объекты не обладают таким свойством, и это коренное различие, не существует "алгебры объектов", то есть она может и существует но наверное объекты для этого должны удовлетворять некоторыми математически верифицируемыми условиям. какими - не знаю, это довольно мутная область имхо.

кстати, вы читали Третий Манифест ну и всю эту байду? насколько я могу судить, единственное непротиворечивое с точки хзрения математики напраление - это вот эта доменная модель, или как там её. вот недаром же приходят все равно к OQL. но это все равно Query Language, а не набор "связывающих" операций.

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

впрочем, вот ещё вопрос. вот вы когда работаете с базой - вы с проектирования чего начинаете? то есть вот генерация схемы - это уже производная объектной модели?
 

StUV

Rotaredom
Пересвязки между сущностями не входят в ORM-либу; они задаются в описании модели, которое является частью конкретного приложения.
Нет. Они являются частью объекта.
я про это и говорил...

а в самой схеме данных в базе эти пересвязки тоже заданы? или только в коде ?

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

---

для меня единственной необходимостью маппинга кода на схему может быть автогенерация схемы по коду
в вашем случае можно сделать такой парсер-билдер ?

ну или обратной преобразование =)

или для каждой конкретной задачи свой шаманский подход ?
 

whirlwind

TDD infected, paranoid
но объекты не обладают таким свойством, и это коренное различие, не существует "алгебры объектов", то есть она может и существует но наверное объекты для этого должны удовлетворять некоторыми математически верифицируемыми условиям. какими - не знаю, это довольно мутная область имхо.
Тут фича в том, что любой запрос:
1. Оперирует полями таблиц, которые грубо говоря являются атрибутами объекта. Т.е. они уже могут быть представлены в виде объекта. Для себя я вывел понятие частичная/ограниченная операция. Это может быть SELECT или UPDATE в случае когда некоторые атрибуты объекта (но не все) были частично изменены. Т.е. фактически мы можем работать с любым результатом, если хотя бы одно поле можно отнести к декларированной сущности - у нас есть объект. С одной стороны это не правильно, но с другой стороны - позволяет сужать специфику результирующего запроса, там где не нужны полноценные объекты.
2. Произвольных выражений, результат которых нельзя сопоставить с атрибутом какой-либо сущности. Здесь сложнее, но не настолько что бы опускать руки. Такой "неправильный" запрос не может быть сгенерирован объектом, потому что они не настолько умны. А если это ручной запрос, то и разбор таких "неприкаянных" данных мы оставляем на откуп программисту.

fisher
нужны какие-то более умные методы проверки...

Ну знаете, мы тут не на экземене вроде. Может и Вы нам что нибудь покажете. Что нибудь такое, что продемонстрирует Ваш печальный опыт использования ORM. Банальное "ниасилил" я как то за аргумент принять не могу, извините.

-~{}~ 04.10.06 13:04:

для меня единственной необходимостью маппинга кода на схему может быть автогенерация схемы по коду
в вашем случае можно сделать такой парсер-билдер ?
Дружище, дак давно ужо показывалось. Нам нужны объекты, а не таблицы. По этому обратного преобразования не предусмотрено.

Простой пример
PHP:
addTableIfNotExists(MetaData::createObject("Reference.Constant"));
addTableIfNotExists(MetaData::createObject("Reference.CategoryType"));
addTableIfNotExists(MetaData::createObject("Reference.Category"));
addTableIfNotExists(MetaData::createObject("Reference.ProductType"));
addTableIfNotExists(MetaData::createObject("Reference.Product"));
addTableIfNotExists(MetaData::createObject("Map.ProductCategory"));
Кусок более сложного, где используется пакетная инициализация

PHP:
MetaData::init(MetaData::createObject("Reference.MenuItem"),true);
MetaData::init(MetaData::createObject("Reference.Constant"),true);
MetaData::init(MetaData::createObject("Reference.Group"),true);
MetaData::init(MetaData::createObject("Reference.User"),true);
MetaData::init(MetaData::createObject("Map.User2Group"),true);
MetaData::init(MetaData::createObject("Reference.CategoryType"),true);
 

bkonst

.. хочется странного?...
fisher
Ну, раз уж мы затронули Третий Манифест и описанную в нем доменную модель, то можно вспомнить, что с точки зрения его авторов, "домены и объектные классы - это одно и то же".

Если допустить существование Object Identity (а оно так или иначе существует, не в виде явного PK, так в виде указателя на область памяти, где этот хранятся данные этого объекта), и не лезть в дебри "идеологически правильной ссылочной целостности", а использовать существующие механизмы, то отображение набора объектов на relvar - дело извлечения вектора атрибутов объекта и (правильное) замены Object Identity на некоторый тип (скажем, длинное целое), реализованный в базе.

Далее, OQL - это просто унифицированный (что очень важно - SQL хорош именно тем, что на него есть стандарт) способ записать запрос. "Псевдокод", который я приводил в качестве примера - это лишь способ собрать семантическое дерево запроса без необходимости писать парсер OQL, делать обработку ошибок и т.п.

Для меня схема данных - производная модели, создаваемая автоматически.

StUV
а в самой схеме данных в базе эти пересвязки тоже заданы? или только в коде ?
При генерации схемы данных поля, объявленные как FOREIGN KEY создаются, естественно. Или вас интересует транзитивное замыкание связей?

я использую более эффективный
Да ну? Дублирование информации о связях в куче мест теперь называется эффективностью?

для меня единственной необходимостью маппинга кода на схему может быть автогенерация схемы по коду
в вашем случае можно сделать такой парсер-билдер ?
Билдер - есть уже в куче существующих реализаций ORM. Обратное преобразование из 3НФ - возможно, но (мне) не нужно в силу того, что сначала разрабатывается модель.
 

Raziel[SD]

untitled00
whirlwind
Банальное "ниасилил" я как то за аргумент принять не могу, извините.
Разве кто-то сказал, что он не осилил ? Сказано было что поддержка таких проектов сложнее т.е. дороже.
 

whirlwind

TDD infected, paranoid
bkonst

Если
>схема данных - производная модели
то
>преобразование из 3НФ - возможно
неверно

-~{}~ 04.10.06 14:15:

Raziel[SD]

Чем его "поддержка таких проектов сложнее т.е. дороже."
отличается от моего "поддерживать такие проекты легче"?

Я код привожу в качестве аргументов. У меня есть проекты. От него кроме слов я пока ничего не видел. Он не привел в пример не одной сложности, с которой действительно приходтся сталкиваться при разработке ORM-based. Все его аргументы - постройте мне вот такой вот запрос.
 

bkonst

.. хочется странного?...
Если
>схема данных - производная модели
то
>преобразование из 3НФ - возможно
неверно
Уточняю - возможно воссоздать набор классов/атрибутов/связей, соответствующих той же модели, что и заданная 3НФ. Полное описание модели содержит в себе больше информации.

-~{}~ 04.10.06 14:28:

Разве кто-то сказал, что он не осилил ? Сказано было что поддержка таких проектов сложнее т.е. дороже.
Всех или некоторых? Во второе - верю сразу и во веки веков; серебряной пули нет. В первое - не верю, прошу доказательств.
 

StUV

Rotaredom
Дублирование информации о связях в куче мест теперь называется эффективностью?
да, если речь о plain-sql в коде
эффективность в поддержке и расширении, я уже об этом писал

повторюсь, без единого стандарта на ORM все эти примеры на псевдо коде - игрушки - т.е. я могу написать так, а могу вот так и еще как-нибудь - новому члену команды понадобится много времени для того чтобы в это въехать

+ можете привести свой "корпоративный" стандарт кодинга в рамках ORM - именования при расширении иерархии наследования, именования методов и т.п... - или для каждого проекта свои стандарты, зависящие от конкретной модели ?
 

bkonst

.. хочется странного?...
да, если речь о plain-sql в коде
эффективность в поддержке и расширении, я уже об этом писал
Ага-ага. Меняем модель из примера про туристов - Route:Company будет относиться как N:M вместо N:1. Пожалуйста, ваши действия. Замечу, что "псевдокод" менять не потребуется вообще.

можете привести свой "корпоративный" стандарт кодинга в рамках ORM
Стандарт кодинга вообще - можем. Стандарт кодинга в рамках ORM - нет, так как ORM пока обкатывается. От модели ORM вообще не зависит.
 

Raziel[SD]

untitled00
Автор оригинала: bkonst
Всех или некоторых? Во второе - верю сразу и во веки веков; серебряной пули нет. В первое - не верю, прошу доказательств.
Какие именно нужны доказательства ?
 

bkonst

.. хочется странного?...
Автор оригинала: Raziel[SD]
Какие именно нужны доказательства ?
Да откуда ж я знаю? Я, что ли это должен доказывать? Покажите, что в любых условиях TCO будет больше. Или используйте "некоторых" вместо "всех".

...Чуть ли не в каждом втором посте заявляю, что ORM имеет собственную ограниченную нишу. И наоборот, чуть ли не в каждом втором посте вижу что кто-то "имел опыт работы с криво написанным/использованным/недокументированным ORM, поэтому сама идея ORM - дерьмо".
 

StUV

Rotaredom
Ага-ага. Меняем модель из примера про туристов - Route:Company будет относиться как N:M вместо N:1. Пожалуйста, ваши действия. Замечу, что "псевдокод" менять не потребуется вообще.
ну и что - какая разница - паблик псевдо-код останется неизменным, а приватные связи модели все-равно придется перестраивать

т.е. в рамках orm - такое изменению схемы приведет к правке связей в орм-классах

при plain-sql - надо будет править запросы - в случае использования шаблонных запросов - правка тоже будет только в одном месте.

---
зы: в моем случае вообще никакой правки не будет - т.к. у нас внутренний стандарт - изменение схемы не влияет на интерфейс хранимых процедур ;)

-~{}~ 04.10.06 16:53:

чуть ли не в каждом втором посте вижу что кто-то "имел опыт работы с криво написанным/использованным/недокументированным ORM, поэтому сама идея ORM - дерьмо".
повторяю - не был он "криво-написанным"
просто любое изменение схемы влечет изменение классов замаппленых на схему или plain-sql запросов - имхо, второй вариант всегда проще "для средне-статистического программера"... - т.е. в своих собственноручно написанных либах вы сами ессно прекрасно ориентируетесь... - но попробуйте сейчас обменяться этими либами с другой конторой, использующей orm или попробуйте переписать все на sql - уверен, второй вариант займет намного меньше времени
 

bkonst

.. хочется странного?...
т.е. в рамках orm - такое изменению схемы приведет к правке связей в орм-классах

при plain-sql - надо будет править запросы - в случае использования шаблонных запросов - правка тоже будет только в одном месте.
Сравниваем объем правок? В первом случае - только описание двух взаимодействующих классов (в предлагаемом варианте - замена has_many/belongs_to на many_to_many - две строчки). Во втором все шаблонные запросы, использующие эту связь (в том числе и не использующие эти два класса напрямую).

-~{}~ 04.10.06 17:02:

повторяю - не был он "криво-написанным"
Он был "недокументированным"?
 

whirlwind

TDD infected, paranoid
>повторяю - не был он "криво-написанным"

Был, был. Ты сам говорил - сложно сделать то-то и сё-то. Для меня именно это является кривостью, а не то как там скобки фигурные расставлены. А если бы чувак, который это писал, был продвинутым, он мог бы например сделать объект запроса Observable и кидать перед компиляцией Event, в которой этот самый еще неоткомпилированный запрос и засовывал. В этом случае все сводится к регистрации Listener-а и реализации любой какой вашей душе угодно специфики. И реализовывать модификаторы отдельными классами и складывать их красиво в отдельную папочку что бы они легко находились. Да мало ли как еще можно было по нормальному сделать. Все упирается в кривые руки.

А это

просто любое изменение схемы влечет изменение классов замаппленых на схему или plain-sql запросов
совсем из другой оперы. Достаточно сравнить насколько часто меняется схема и насколько часто логика.
 

StUV

Rotaredom
а что теперь отсутствие документации - признак кривости кода ?

даже с учетом наличия документации времени на вникание в суть ОО-либы требуется намного больше, чем на изучение нового для себя диалекта sql.

--
зы:
одна из наиболее полных документаций из тех что я видел - это доки к Qt - но на изучение некоторых иерархий наследования одной документации часто недостаточно - приходится лезть в исходники

В первом случае - только описание двух взаимодействующих классов
если заранее знаешь всю либу вдоль и поперек - наверно да, правок меньше

а если - вот тебе доки, вот старые схема/код, вот новые требования..... - сразу все меняется местами
 
Сверху