Модели в фреймворках

fixxxer

К.О.
Партнер клуба
Именно! Но вот в доках этих инфраструктурных библиотек как раз "доменные" примеры "из жизни"
Ну что ж поделать. Простым всегда кажется не то, что проще по объективным причинам (всяким там метрикам), а то, что знакомо, для чего не требуется усваивать какие-то новые концепции. Когда-то мы все писали ужасный спагетти-код, а всякие там разделения на слои понять было сложно. Сейчас же, если откопать свой код столетней давности, окажется, что разобраться в нем и внести даже небольшие изменения - сложно.

Если ты хочешь ответа на вопрос, что с этим делать, у меня нет ответа. :)
 

fixxxer

К.О.
Партнер клуба
Кстати насчет кеширования очень хорошо в cycle сделано - явно указываемая куча, как результат значительно меньше шансов получить неприятный нежданчик.
Полагаю, так сделано из других соображений: в первой же строке вводной части документации говорится: designed to safely work in classic and daemonized PHP applications.

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

Yoskaldyr

.
Партнер клуба
в первой же строке вводной части документации говорится: designed to safely work in classic and daemonized PHP applications.
Может изначально и из-за этого, но в доке где-то было зачем может понадобиться и как создавать кучу. Лично для меня это добавляет явности при работе со сложными write моделями, не надо думать что где-то что-то закешировалось. Изменение данных всегда предсказуемо. Лучше еще раз дернуть из базы новые данные (которые могут уже быть совсем другие, а не те что в кеше орма), чем потом разгребать баги связанные с параллельным обновлением данных.
 

fixxxer

К.О.
Партнер клуба
не надо думать что где-то что-то закешировалось
Самый простой способ не думать о том, что где-то что-то закэшировалось - не кэшировать. Часто кэшируют не потому что измерили и нашли bottleneck, а на всякий случай. :)

Да и тот же lazy load при разумно спроектированных aggregate roots не нужен. Если нужен, значит, надо побить помельче.
 

Yoskaldyr

.
Партнер клуба
Самый простой способ не думать о том, что где-то что-то закэшировалось - не кэшировать
многие ормы кешируют by default, во избежание дополнительных запросов на чтение (тот же cycle, но там легко управлять используя отдельные кучи)
 

fixxxer

К.О.
Партнер клуба
Спасибо, Костя.
Я честно дого втыкал, но не очень понял, почему
Из-за базового предположения, что 1 класс мапится на 1 таблицу (и, как следствие, связи между классами однозначно мапятся на тот или иной вид реляционного отношения), нет способа описать маппинг, пересекающий эти границы.

Тут я, конечно, имел ввиду существующие реализации типа Eloquent или Yii AR, которые все копируют RoR ActiveRecord с несущественными отличиями. В принципе active record, в котором маппинг задается на уровне aggregate root, написать не проблема (хотя бы потому, что из любого датамаппера можно сделать активрекорд).

Cycle, кстати, тоже не без этой проблемы, но он достаточно гибок и легко расширяем, чтобы ее решить. Местами нетривиально, но точно намного проще, чем писать свою ORM.
 

Фанат

oncle terrible
Команда форума
Из-за базового предположения, что 1 класс мапится на 1 таблицу
Круто. Это мне как-то в голову не пришло. Получается, именно это является характеристическим свойством AR.
Офигеть, пошел прочитать. An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data.
Выделенное почему-то всегда проходило мимо моего (весьма узкого) фокуса внимания.
Ну да, так становится куда яснее, зачем нам разносить объект и маппер. В ДМ мы гораздо свободнее в своих отношениях.

Но при этом традиционные модельки в Симфони, которые клепаются всякими кодогенераторами, по сути тоже делают объекты, представляющие строку из датабазы.

И мой игрушечнный DM, который я клепаю в свободное от работы время, тоже занимается такой же фигнёй. Блин.
 

fixxxer

К.О.
Партнер клуба
Получается, именно это является характеристическим свойством AR.
Это смотря что считать ActiveRecord-ом. Если RoR-овский и его клоны, то конечно. А если взять обобщенное определение Фаулера - там таких ограничений не накладывается.

Я в какой-то момент осознал, что то, что я писал ручками до всяких ORM, это по сути были почти что Aggregate Roots с ручным ActiveRecord (в обобщенном понимании): я ведь мог запросто пройтись по «вложенным» моделям и выполнить кучу sql-запросов в транзакции. Конечно, на самом деле это все часто было ближе к тупым transaction script - но не всегда.

Но при этом традиционные модельки в Симфони, которые клепаются всякими кодогенераторами, по сути тоже делают объекты, представляющие строку из датабазы.
Дык, я с того и начал, что если вместо domain models писать банальные persistence models, чем, по сути, сводя всю бизнес-логику к процедурному стилю, то обсуждать преимущества или недостатки Data Mapper vs Active Record несколько бессмысленно.
 

fixxxer

К.О.
Партнер клуба
В опенсорсе ты такое вряд ли увидишь, а проприетарным кодом делиться, сам понимаешь, не могу. :)
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
можно взять ROR-style объекты, и использовать их как источник данных, написав ORM-слой с маппингом логики на базу, но не через SQL, а через сгенерированные классы
 

Yoskaldyr

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

Yoskaldyr

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

P.S. На днях думаю еще одну срачетемку создать (уже без извращений)
 

fixxxer

К.О.
Партнер клуба
Погоди, откуда взять? Я процитированный кусок взял отсюда: https://www.martinfowler.com/eaaCatalog/activeRecord.html
Блин, я настолько был уверен, что помню написанное в книге, что даже не перечитал. Вот идиот-то!

Сейчас вот перечитал, а там и определение такое же, как по ссылке (которую я же, блин, и дал!), и еще вот:


В общем, почти каждый мой тезис там можно найти в том или ином виде, на самом деле. Читать надо было внимательнее, блин, можно было бы тупо ссылок накидать вместо простыни. :)

Хотя чисто технически я все равно не вижу проблем с расширением Active Record до варианта с "Data Mapper, совмещенный с Aggegare Root": иначе как такой вариант вообще назвать? Наверное, поэтому и была такая "ложная память": дырка в списке паттернов получается. :)
 

Фанат

oncle terrible
Команда форума
можно было бы тупо ссылок накидать вместо простыни. :)
НУ ЩАС
Твои-то куда более образные и понятные. У Фаулера, будь он здоров тыщу лет, все-таки сухой язык компьютерной документации, у тебя гораздо доходчивее.

Хотя конечно разница в конечном итоге формулируется как раз цитатой из твоего скриншота:

Если у тебя простые сущности, которые тупо мапятся на таблицы, то пофиг что юзать, AR проще.
Если бизнес-логика уже сейчас не впихуется в реляционную структуру, или если думаешь на будущее - то бизнес-логику пиши в доменную сущность, а логику её маппинга на БД - в сопстствующий маппер.

Ну и плюс твои рассуждения про объектность подхода, которые я, своим линейным умом в общем понимаю, но с применением их на практике очень большие проблемы.
 

Adelf

Administrator
Команда форума
Ну и плюс твои рассуждения про объектность подхода, которые я, своим линейным умом в общем понимаю, но с применением их на практике очень большие проблемы.
У нас Вурдалак любил приводить в пример игры. Я взял на вооружение игру Монополия. Представь себе ее модель. Это будет один агрегат огромный Игра. Там будут Игроки, Поле и т.д. Когда один игрок ходит, то бросается кубик, фишка игрока сдвигается на какой-то поле и в зависимости от того, какое это поле происходят различные события. Собственность чужого игрока - надо заплатить. Есть деньги - платишь. Нет - придется что-то делать. И вот такой огромный агрегат, когда думаешь как его смоделировать, мысль о том, как всё хранить, возникает далеко не в первую очередь. В таких примерах сразу становится очевидным верховенство правильной объектной модели над строками в базе данных.
 

fixxxer

К.О.
Партнер клуба
Хотя конечно разница в конечном итоге формулируется как раз цитатой из твоего скриншота:
Вот да. Забавно, что я на это не обратил внимание сколько-то там лет назад, сконцентрировавшись в основном на примере кода на Java (в котором, в общем-то, никакой строгой привязки к таблице нет, никто не мешает написать "ручной маппинг" как угодно).

Читал бы внимательнее, понял бы это все лет на 10 раньше. Или не понял бы (я не очень умный, до меня долго доходит, пока сам все в голове по полочкам не разложу самостоятельно и не приду к тем же выводам через цепочку рассуждений "с самого начала").
 
Последнее редактирование:
Сверху