Сервисы и репозитории. Слоистая архитектура. Примеры.

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

Re: Сервисы и репозитории. Слоистая архитектура. Примеры.

Сообщение ElisDN »

Sam Dark писал(а):Всегда можно инстанциировать тот или иной компонент напрямую, всегда можно полезть и достать из контейнера явно что-либо ну и т.д. Чёрный ход есть всегда и везде... Как буд-то из DI-конейнера явно получить коннекшн лучше, чем вытащить его из репозитория...
Ну топик этот, вроде бы, практический. Так что ждём примеров, как получить коннекшн внутри сущности class Product { ... } или из Twig'а в Symfony.

zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Сервисы и репозитории. Слоистая архитектура. Примеры.

Сообщение zelenin »

Sam Dark писал(а):Ну ладно :) Технически ни один фреймворк ни на одном известном мне языке не может запретить сделать прямой запрос в базу будь то средствами PDO
PDO - часть языка. Вещь низкоуровневая. Если человек САМ инстанциирует коннекшн ПДО (прописывает логин/пароль, адрес сервера итд) вместо того, чтобы спросить у коллег "а как это у нас делается в проекте", то либо он знает что делает либо неадекват. А AR (и любой глобально доступный инструмент) напрямую может использовать любой yii-шник.
Sam Dark писал(а): query builder-а или ещё чего
если у нас нет yii, у нас нет и query builder, который глобально доступен.
Sam Dark писал(а): Всегда можно инстанциировать тот или иной компонент напрямую, всегда можно полезть и достать из контейнера явно что-либо ну и т.д. Чёрный ход есть всегда и везде.
обсуждаем черти что.
Хочешь сделать архитектурно хорошее приложение, выкинь сразу все неудовлетворяющее минимальным входным требованиям.
Можно репозиторий построить на AR. Вопрос: зачем?

Слои - это о взаимозаменяемости, интерфейсах, адаптерах, слабой связанности. Если у нас есть AR, то мы забыли обо всех этих принципах. Прибегает slavcodev: ты просто не умеешь их готовить. Начинаем готовить AR - убираем встроенную валидацию, т.к. валидацию нужно вынести в отдельный сервис - если мы будем валидировать входные ДТО (а нам нужно валидировать), то нам нужно будет писать какой-то свой слой валидации или пользоваться yii-шными валидаторами standalone. Плюс сущности ddd унас должны быть всегда валидными, т.е. валидация должна быть вне. Убираем поведения, т.к. они достаточно не явны, фреймворкозависимы, и вообще мы обходимся ubiquitose language и его "сеттерами" и сервисами. Подменяем db в модели на внешний, т.к. di, и опять зависимость от фреймворка (черт, да сам AR уже зависимость от фреймворка - мы пытаемся дотянуть yii до уровня слоистой архитектуры, хотя это лишь замазывание ржавчины краской). И вот у нас есть подобие сущностей, и встает вопрос: а зачем нам нужно было AR готовить, если в итоге AR хотели использовать именно за встроенную валидацию, связи, встроенный коннекшн и поведения? Так а хотим мы вообще слоистую архитектуру, если сознательно отказываемся от ее принципов?

Разработчик, спрашивающий можно ли использовать AR в слоистом приложении, не понимает какие задачи решает слоистое приложение.
Слоистое приложение - это framework-agnostic приложение, соединяющее слои через адаптеры - реализации интерфейсов.

zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Сервисы и репозитории. Слоистая архитектура. Примеры.

Сообщение zelenin »

Sam Dark писал(а):Как буд-то из DI-конейнера явно получить коннекшн лучше, чем вытащить его из репозитория...
если ты получил коннекшн из diс, то ты уже на следующей ступеньке. Тебе осталось обернуть его в сервис и заюзать.
AR - это из другой оперы. Он тебе шепчет: используй меня, я глобально доступен - ты пять лет провел со мной, мы знаем друг друга.
Поэтому просто выкидываем все из прошлой жизни и начинаем жить по новому, не пытаясь пристроить старые инстурменты к новым реалиям.

Аватара пользователя
samdark
Администратор
Сообщения: 9362
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Сервисы и репозитории. Слоистая архитектура. Примеры.

Сообщение samdark »

Не, ну понятно, что AR развращает и если надо репозиторий, то, хоть технически и ничему не противоречит заюзать внутри него AR, лучше не надо. Тут спору нет.

ElisDN

В Symfony не все пользуются Twig-ом. Если юзается Twig, в Yii получается та же техническая защита View, что и в Symfony.

На тему как сделать плохо, гуглится за минуту:

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

global $kernel;
$db = $kernel->getContainer()->get('db_connection');‏
$users = $conn->fetchAll('SELECT * FROM users');
Конечно, за такое и подобное что в Symfony, что в Yii надо руки с корнем вырывать. Но технически очень просто :)

Аватара пользователя
ElisDN
Сообщения: 5606
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Сервисы и репозитории. Слоистая архитектура. Примеры.

Сообщение ElisDN »

Sam Dark писал(а):Конечно, за такое и подобное что в Symfony, что в Yii надо руки с корнем вырывать.
Ну вот. В Symfony это преступление, пресекаемое оборачиванием кода web/app.php в замыкание, также отлавливаемое синтаксическими анализаторами по словам "global" и "$_GLOBALS" и наказуемое отрыванием рук. А в Yii это повседневная практика с Yii::$app->db и Yii::$app->request с Yii::$app вместо $kernel. Об этом и речь.

Аватара пользователя
samdark
Администратор
Сообщения: 9362
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Сервисы и репозитории. Слоистая архитектура. Примеры.

Сообщение samdark »

А, ну если с этого ракурса подойти, то да, хотя те же синтаксические анализаторы отлично ловят и Yii::$app в определённых директориях. По факту новичкам пофиг и в том и во втором случае. Они способ найдут и кроме как наличием человека, который делает ревью и бьёт по рукам, это не решить.

Аватара пользователя
SiZE
Сообщения: 2699
Зарегистрирован: 2011.09.21, 12:39
Откуда: Perm
Контактная информация:

Re: Сервисы и репозитории. Слоистая архитектура. Примеры.

Сообщение SiZE »

Я думаю это надо вынести отсюда
в поиске работы

Vitalik_yii
Сообщения: 65
Зарегистрирован: 2014.01.13, 10:03

Re: Сервисы и репозитории. Слоистая архитектура. Примеры.

Сообщение Vitalik_yii »

По поводу репозиториев, допускается ли использование репозиториев внутри репозиториев?
Что-то вроде:

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


class PostRepository implements PostRepositoryInterface
{
    public function fetchPopularPosts()    
    {
        $posts = ....;
        $postIds = ...;
        
        $commentRepository = new CommentRepository();
        $comments = $commentRepository->fetchCommentsByPostIds($postIds);
        
        $commentsHashedByPostId = [];
        
        foreach ($comments as $comment) {
            .....
        }
        
        $popularPosts = [];
        
        foreach ($posts as $post) {
            ...
            $popularPosts[] = new PopularPostDTO($post->id, $post->title, (isset($commentsHashedByPostId[$post->id]) ? $commentsHashByPostId[$post->id] : []));
        }
        
        return $popularPosts;
    
    }
}


zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Сервисы и репозитории. Слоистая архитектура. Примеры.

Сообщение zelenin »

допускается, через DI конечно, а не через прямое создание как в примере.
репозиторий возвращает сущности, а не дто.

Vitalik_yii
Сообщения: 65
Зарегистрирован: 2014.01.13, 10:03

Re: Сервисы и репозитории. Слоистая архитектура. Примеры.

Сообщение Vitalik_yii »

zelenin писал(а):допускается, через DI конечно, а не через прямое создание как в примере.
репозиторий возвращает сущности, а не дто.
По поводу DI понял. А вот по поводу сущности, elisdn писал:
ElisDN писал(а):
...

И кстати, есть ещё один лайфхак. Сущность поста блога для выполнения различных операций может содержать связанные категории, метки, фотографии, текст, комментарии, автора, версии и т.п. А выборок на сайте может быть много:

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

Выбирать целиковые громоздкие сущности для этого всего может быть слишком напряжно. Поэтому для вывода на сайте можно сделать второй PostReadRepository чисто для выборок. И он из метода getPopularPosts($limit) вместо массивов оригинальных тяжёлых сущностей Post может возвращать массивы легковесных вмпомогательных DTO вроде $popular[] = new PopularPost($id, $title, $photo, $commentsCount) только с нужными полями. И для их извлечения из базы в репозитории уже можно легко формировать любые отдельные SQL-запросы.

....

Немного запутался. В данном случае "вмпомогательных DTO" подразумевает под собой сущность? Или здесь именно вся суть в PostReadRepository, который возвращает DTO, а PostRepository возвращает сущности?

zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Сервисы и репозитории. Слоистая архитектура. Примеры.

Сообщение zelenin »

в данном случае следует отделять DTO, служащие для переноса данных обычно от реквеста до сервиса, и ReadModel - простая модель без поведения, по определению тоже являющейся дто.
Или здесь именно вся суть в PostReadRepository, который возвращает DTO, а PostRepository возвращает сущности?
типа того.

Аватара пользователя
ElisDN
Сообщения: 5606
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Сервисы и репозитории. Слоистая архитектура. Примеры.

Сообщение ElisDN »

Vitalik_yii писал(а):Или здесь именно вся суть в PostReadRepository, который возвращает DTO, а PostRepository возвращает сущности?
Да, идея в том, что через Repository работать с оригинальными полноценными сущностями в ядре, а через ReadRepository делать лёгкие прямые запросы к базе для вывода на сайте и возвращать результат в ассоциативных массивах или в публичных полях примитивных структур PopularPost. Поэтому первый репозиторий во втором не нужен.

Аватара пользователя
samdark
Администратор
Сообщения: 9362
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Сервисы и репозитории. Слоистая архитектура. Примеры.

Сообщение samdark »

Я думаю, пора эту тему-свалку прикрыть и нормально обсуждать в отдельных темах...

Закрыто