DDD и сортировки/фильтрации

Обсуждаем, как правильно строить приложения
Ответить
shurup312
Сообщения: 20
Зарегистрирован: 2012.12.07, 17:50

DDD и сортировки/фильтрации

Сообщение shurup312 »

Привет, форумчанам. С удивлением обнаружим на форуме топики по DDD и решил задать вопрос сюда. Сам ответ так и не могу найти.
Как вывести в таблицу данные, которые относятся к нескольким сущностям в целом понятно. Можно их по отдельности выбернуть и перемаппить. А вот как потом по этой выборке сделать фильтрации или сортировки так, чтобы это было именно в DDD принципах реализовано.
Вот для примера, выводятся у меня дети с именами родителей. Есть у нас сущность "человек". Мы дергаем всех людей-детей, потом по детям дергаем людей-родителей, маппим и выводим. Используем что-то типа
$childredCollection = $this->get('people_repository')->getChildren();
$parentsCollection = $this->get('people_repository')->getByCollection($childredCollection);
ну и потом маппим как-то. А как вот так же понятно и удобно внедрить сюда сортировки/фильтрации?
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: DDD и сортировки/фильтрации

Сообщение ElisDN »

Код: Выделить всё

$list = $this->get('people_view_repository')->getChildrenWithParents($filter, $sort, $offset, $limit);
shurup312
Сообщения: 20
Зарегистрирован: 2012.12.07, 17:50

Re: DDD и сортировки/фильтрации

Сообщение shurup312 »

Идея мне нравится, потому что она дает решение, как делать. Фильтры и сортировки можно запилить вэлью объектами,чтобы это был не просто массив, а опять же объектный подход.
Но все же это уже будет не предметно-ориентированный репозиторий, а чисто технический, стандартный ООП.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: DDD и сортировки/фильтрации

Сообщение zelenin »

shurup312 писал(а):Но все же это уже будет не предметно-ориентированный репозиторий, а чисто технический, стандартный ООП.
поясните мысль.
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: DDD и сортировки/фильтрации

Сообщение ElisDN »

shurup312 писал(а):Но все же это уже будет не предметно-ориентированный репозиторий, а чисто технический, стандартный ООП.
Это отдельный view-репозиторий, добавленный чисто для выборок ради вывода на сайте.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: DDD и сортировки/фильтрации

Сообщение zelenin »

ElisDN писал(а):
shurup312 писал(а):Но все же это уже будет не предметно-ориентированный репозиторий, а чисто технический, стандартный ООП.
Это второй репозиторий, добавленный чисто для выборок ради вывода на сайте.
зачем? почему в рамках одного нельзя все сделать? листинг данных - вполне ddd задача.
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: DDD и сортировки/фильтрации

Сообщение ElisDN »

zelenin писал(а):зачем? почему в рамках одного нельзя все сделать? листинг данных - вполне ddd задача.
Если на сайте стопицот виджетов и листингов, требующих кучу выборок с разными JOIN-ами, фильтрами и счётчиками, то тяжёлые агрегаты с кучами лишних данных и медленной гидрацией не особо уместны. В таких случаях по мотивам CQRS предпочитаю помимо оригинального медленного доменного репозитория:

Код: Выделить всё

namespace Domain\Repository;

class PostRepository
{
    function get($id): Post
    function add(Post $post)
    function remove(Post $post)
} 
делать отдельный View, работающий с Raw SQL, ElasticSearch, Redis и прочими быстрыми хранилищами и возвращающий DTO или массивы с нужными для каждой выборки данными:

Код: Выделить всё

namespace ReadModel;

class PostFetcher
{
    function find($id): ?PostDetailView
    function countAll()
    function getAll($offset, $limit, $sort): PostListView[]
    function countPublished()
    function getPublished($offset, $limit)
    function countForUser($userId)
    function getForUser($userId, $offset, $limit)
    function countForTag($tagId)
    function getForTag($tagId, $offset, $limit)
    function getPopular($limit)
    function getResent($limit)
} 
вместо запихивания всех этих методов (или груды спецификаций) в доменный репозиторий.
Последний раз редактировалось ElisDN 2019.03.28, 00:21, всего редактировалось 5 раз.
shurup312
Сообщения: 20
Зарегистрирован: 2012.12.07, 17:50

Re: DDD и сортировки/фильтрации

Сообщение shurup312 »

zelenin писал(а):
shurup312 писал(а):Но все же это уже будет не предметно-ориентированный репозиторий, а чисто технический, стандартный ООП.
поясните мысль.
Ну когда мы говорим про человека как сущность, то все понятно. И репозиторий создается под него. А когда мы говорим про репозиторий под беренокПлюсРодители, то это уже выглядит как костыль. И данный репозиторий будет содержать опять же джоины потом, так что если какая-то сущность будет переноситься на другое хранилище, то придется править два репозитория. Плюс не совсем понятно, в какой сущности этот репозиторий хотя бы примерно отнести, потому что у нас тут все просто, по факту репозиторий все равно про людей. А если будет владелец+авто? там будут фигурировать уже две разные сущности. И репозиторий будет относиться частично к каждой, но по факту сам по себе, уже скорей как сервис вырисовывается, а не как репозиторий.
Следующий момент - опять же, ну сделали мы репозиторий с join'ом, допустим, если у нас это в мускуле. А потом одна из сущностей решила уехать в MongoDB, тогда вообще ступор.
Хотя тут уже может я перегибаю конечно, и можно просто хранить данные нормализованные как чистый источник данных и данные денормализованные для этой конкретной выборки. В принципе тоже как вариант, правда тогда нужно будет для этого доп.средства записи этих самых денормализованных данных внедрять и не допускать их инвалидации.
shurup312
Сообщения: 20
Зарегистрирован: 2012.12.07, 17:50

Re: DDD и сортировки/фильтрации

Сообщение shurup312 »

Ну и кстати посмотрев на репозиторий
namespace ReadModel\Repository;

class PostReadRepository
{
function get($id): PostDetailView
function countAll()
function getAll($offset, $limit, $sort): PostListView[]
function countPublished()
function getPublished($offset, $limit)
function countForUser($userId)
function getForUser($userId, $offset, $limit)
function countForTag($tagId)
function getForTag($tagId, $offset, $limit)
function getPopular($limit)
function getResent($limit)
}

понимаю, что он все равно плохо решает проблему. у нас же могут быть выборки типа первые десять с группировкой по дате в интервале с 1 января по 10ое полько пользователей с именем вася и возрастом 20-34 года. Я не буду пилить метод для конкретно такой выборки. у нас таблица, над ней обычно фильтр, вот в него могут ввести произвольно что угодно
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: DDD и сортировки/фильтрации

Сообщение zelenin »

формируйте QueryObject и под него один универсальный метод - где-то обсуждали.
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: DDD и сортировки/фильтрации

Сообщение ElisDN »

Для произвольного поиска так и сделайте:

Код: Выделить всё

function getAllByCriteria($criteria, ...)
anton_z
Сообщения: 483
Зарегистрирован: 2017.01.15, 15:01

Re: DDD и сортировки/фильтрации

Сообщение anton_z »

Да в CQRS вообще рекомендуют ORM не использовать. Лучше всего подойдет SqlDataProvider или AR. Для списков важна скорость. Если нужны проверки по статусам, датам и др, можно их сделать в AR из которых будете показывать. Да, дублирование, но, как говорится, you have to pay somewhere. Оно не будет сильно страшным. Я считаю, что DDD это не про чтение, это про запись. Не надо делать списки используя DDD в уii - потеряете все DataProvider и Pagination, да и в других fw тоже не стоит.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: DDD и сортировки/фильтрации

Сообщение zelenin »

anton_z писал(а): 2017.01.15, 15:39Да в CQRS вообще рекомендуют ORM не использовать
а тут про орм речь-то и не идет.
anton_z писал(а): 2017.01.15, 15:39Лучше всего подойдет SqlDataProvider
yii-шный? да тут и про yii речь не идет.
anton_z писал(а): 2017.01.15, 15:39или AR
ar - паттерн орм.
anton_z писал(а): 2017.01.15, 15:39Для списков важна скорость. Если нужны проверки по статусам, датам и др, можно их сделать в AR из которых будете показывать. Да, дублирование, но, как говорится, you have to pay somewhere. Оно не будет сильно страшным. Я считаю, что DDD это не про чтение, это про запись. Не надо делать списки используя DDD в уii - потеряете все DataProvider и Pagination, да и в других fw тоже не стоит.
ну ddd действительно скорее про запись, чем про чтение, но тема-то о другом: как гибко создать read-репозитории.
anton_z
Сообщения: 483
Зарегистрирован: 2017.01.15, 15:01

Re: DDD и сортировки/фильтрации

Сообщение anton_z »

А, ну я неверно выразился, прошу прощения. Попробую уточнить.
Думается мне, что само создание read-репозиториев дело не благодарное и не эффективное для сортировки/фильтрации. Что возвращать из этих репозиториев? Сущности? Их же создать, данными заполнить. Здесь нет сложности, управлять которой призвано DDD.
Последний раз редактировалось anton_z 2017.01.15, 17:32, всего редактировалось 1 раз.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: DDD и сортировки/фильтрации

Сообщение zelenin »

anton_z писал(а): 2017.01.15, 17:29 А, ну я неверно выразился, прошу прощения. Попробую уточнить.
Думается мне, что само создание read-репозиториев дело не благодарное и не эффективное. Что возвращать из этих репозиториев? Сущности? Их же создать, данными заполнить.
readmodel'и
Ответить