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

Yoskaldyr

.
Партнер клуба
@fixxxer все это понятно!
.Я говорил немного о другом. Вместо того чтобы писать простыню кверибилдера или этажи сложного запроса и потом это все поддерживать, дергать 1-2 методами учитывая существующую схему описанную в датамеппере. Все.
Одна проблема нужны ограничения чтобы в принципе нельзя было хоть как-то изменить.
Т.е. это ридонли датамеппер используется только для чтения и в нем физически выпилена/заблокирована возможность что либо менять, да защита от дурака, но даже при постоянном ревью можно пропустить. Плюс эджкейсы когда данных очень много (тоже бывают нюансы связанные с ненужной инфой в записях/строках датамепперов/тейблгейтвеев) и когда датамеппер любит все кешировать неявно.
Учитывая все нюансы понятно что все любят писать просто запрос или через квери билдер - очень предсказуемо и нет сайдэффектов, но это релаьно нудно, особенно на большом количестве полей и связей и поддерживать при изменении схемы вообще гемор.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
опять смешались люди, кони ...
как теоретически возможно не редактировать код во всех местах, где используются поля объекта, когда одно из полей удаляется?

когда обращения написаны явно, без магии, это делается просто, IDE покажет все использования, а магия, облегчив написание кода, изменения затрудняет
 

Yoskaldyr

.
Партнер клуба
конечно приходится править, но зачем количество таких мест увеличивать в разы?
 

grigori

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

fixxxer

К.О.
Партнер клуба
Не вижу, где я предлагаю писать больше.
Скажем, автомаппер на соглашениях - это намного менее нудно, чем полноценно расписывать маппинг.
Если уж на то пошло - больше всего писанины вообще из-за убогости php, с отсутствием public final | readonly свойств. Геттеры, конечно, в IDE автоматом генерируются, но все равно.
 

ksnk

прохожий
там ( фио, фото, статус пользователя, количество друзей ...
я не очень понял претензии к Read Model. На мой взгляд, моделька должна уметь заказывать получение определенного, нужного в данный момент, набора полей. Возможно, можно даже автоматизировать эти "заказы", но мне пока не кажется это оправданным...
Так можно обойтись одной моделькой для одной сущности и не терять возможность иметь в меру оптимальные автоматические запросы на получение данных...
 

Yoskaldyr

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

с отсутствием public final | readonly свойств
а то что нет этого - да сильно бесит. Приходится извращаться или с магическими геттерами и сеттерами с разными грязными хаками, но только если нужна полная иммутабельность или просто @property-read коммент если достаточно предупреждения в сторме
 

fixxxer

К.О.
Партнер клуба
я имел ввиду прямые запросы к базе (текстом или через кверибилдер - не важно)
В запросах для read models очень часто будет то, чего ни в каком двустороннеем датамаппере быть не может - всякие count-ы, group by, order by, да хоть window-функции и прочие CTE. Где-то же эта сложность должна отразитсья. Пытаться сделать декларативную обертку вокруг кверибилдера? Сразу нафиг, точно будет текущая недоабстракция.
 

Yoskaldyr

.
Партнер клуба
В запросах для read models очень часто будет то
частотность зависит от проектировки базы и от количества денормализованных данных в ней. если для выбора данных ридмоделей часто используются group by и count, значит явно что-то не так со структурой таблиц.
И использование описанной в датамеппере/тейблгейтвее структуры таблиц, никак не мешает использовать запросы напрямую. Но постоянно их писать - это сомнительное удовольствие
 

fixxxer

К.О.
Партнер клуба
Ну не знаю, как по мне, денормализация без полноценного евент сорсинга - это как сразу себе обе ноги отстрелить.

А с евент сорсингом вообще разговор отдельный :)
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
простой пример неавтоматизируемых запросов из нашего с Фанатом прошлого - EAV:

* категории: платья, телефоны, грабли - 50 тысяч записей
* характеристики: цвет, масса, марка, процессор, длина, ширина, ... 10 тысяч записей
* товары (id, артикул, название, описание) - 500 тысяч записей
* товар-категория - m2m связь ... 70 тысяч записей
* характеристика-товар - m2m связь ... 10 млн записей
* допустимая характеристика в категории - m2m связь
* цены на товары - m2m связь

Обычный каталог, выводим раздел граблей с фильтром по цвету, процессоров в фильтре быть не должно. Постранично, конечно. SQL-запрос на 2 экрана. Никакими доктринами такое не сделать.
Автогенерация заканчивается на COUNT - прикольная тема, на нем обламываются все разработчики, привыкшие к ORM.

А Query Builder очень помогает. Можно создать базовый набор JOIN ... WHERE status="active", и в разных ситуациях добавлять разные таблицы с параметрами выборки.
Структура базы и приложение у нас меняются почти каждый день независимо одно от другого.
Нам надо разделить код мапинга данных на объекты и простыню SQL/QB в отдельные классы, чтобы менять их независимо. На выходе - объект с данными, которые нужны для отрисовки страницы, он меняется с полетом фантазии отдела маркетинга.

Такой мапинг с генерацией объекта, в котором только данные, и никакой логики, и становится нашей read model.
 

WMix

герр M:)ller
Партнер клуба
На мой взгляд, моделька должна уметь заказывать получение определенного, нужного в данный момент, набора полей.
Если с точки зрения sql или qb, никаких вопросов select a, b, ... другие поля

Так можно обойтись одной моделькой для одной сущности
А вот тут не очень понятно. Класс уже написан. Какая уже тут динамика?
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Ну не знаю, как по мне, денормализация без полноценного евент сорсинга - это как сразу себе обе ноги отстрелить.

А с евент сорсингом вообще разговор отдельный :)
В общем случае, как мы работаем с базой - неважно.
Можно сгенерить Active Record по таблицам в yii, можно сгенерить таблицы по декларациям в Doctrine. Можно написать запросы с Query Builder и собирать объект с данными руками. Можно сделать запрос к Redis.
Важно собрать объект с данными, закончить работу с базой, и не думать о том, как данные получены, когда пишем обработку этих данных.
 

ksnk

прохожий
А вот тут не очень понятно. Класс уже написан. Какая уже тут динамика?
Хмм... Ну, к примеру, битрикс :)
PHP:
CDBResult
CCatalogProduct::GetList(
 array arOrder = array(),
 array arFilter = array(),
 array arGroupBy = false,
 array arNavStartParams = false,
 array arSelectFields = array() //Массив полей записей, которые будут возвращены методом.
    //Можно указать только те поля, которые необходимы.
    //Если в массиве присутствует значение "*", то будут возвращены все доступные поля.
);
Класс - модель чтения, уже написан. Вот динамика... Это скелетик, конечно, но как скелетик - не так и плох...
Когда нам нужно получить много странных полей - нам в модельке достаточно указать, что хочется еще и темы, количество друзей-хейтеров ets... А моделька, одна.
 

Фанат

oncle terrible
Команда форума
Я все равно не понимаю, почему
В отличие от внутренностей write-моделей, read-модели в подавляющем большинстве случаев "плоские" (или коллекция "плоских").
Если честно, то я окончательно запутался.
В моем понимании, модель только одна. А мапперов получается может быть два - read и write.
Или получается должно быть две модели и два маппера?
или два модели, один маппер?

Если хотим что-то записать, то создаем экземпляр write-model, накачиваем его данными, и скармливаем его мапперу?
Но зачем нам тогда отдельная модель? Разве логика растаскивания данных по хранилищу - это не логика маппера, о которой модель ничего не должна знать?
 

Yoskaldyr

.
Партнер клуба
Обычный каталог, выводим раздел граблей с фильтром по цвету, процессоров в фильтре быть не должно. Постранично, конечно. SQL-запрос на 2 экрана. Никакими доктринами такое не сделать
Ну как всегда, не читаем что пишут другие.
Во первых я ничего не писал насчет доктрины. Доктрина не совсем подходит для чтения - из нее вообще не выпилять часть связанную с записью (да и вообще разработчики доктрины давно перестали понимать как и что у них работает внутри)
И я (да и @Фанат тоже как мне кажется) ничего не писал насчет списков, особенно матрикс фильтров - здесь вообще надо бы сфинкс или эластик использовать. Везде в примерах было тупое ->load($id) такие единичные загрузки со всеми (или не всеми если надо) зависимостями встречается очень часто. И если говорить о сложных выборках списков, то в большинстве случаев сначала сложным запросом (или сфинксом или эластиком) получить список id, а потом по этим id подгрузить все данные с зависимостями.
 

флоппик

promotor fidei
Команда форума
Партнер клуба
В моем понимании, модель только одна.
В некотором идеальном случае, моделей будет столько, сколько у тебя есть доменных областей. Условно, пользователь в момент аутентификации, и пользователь в отображении автора поста, и пользователь в отображении твоего профиля, это разные модели (которые опираются на одну и ту же запись в хранилище данных) - они имеют разную структуру (не нужны же логин и пароль модели автора поста? или количество постов для логина или его темы.
 

Фанат

oncle terrible
Команда форума
В некотором идеальном случае, моделей будет столько, сколько у тебя есть доменных областей.
Тааак, это я могу понять, звучит очень логично.
А с записью что? Тоже много или тут одна?
И главный вопрос - а мапперов сколько? Скажем, нам нужно 3 читательских модели. Сколько мапперов нам надо? Нутром чую что три.
Или ок, read aside, если у нас две write модели, то получается и два маппера?
 
Сверху