Как реализуете репозиторий (Doctrine, Analogue, ручками, etc)

Юрий Быков

Новичок
Все хорошо известен TripPlanner
https://github.com/leopro/trip-planner/blob/master/

Самое интересное место на мой взгляд в контексте вопроса это
https://github.com/leopro/trip-planner/blob/master/src/Leopro/TripPlanner/Domain/Contract/TripRepository.php
а реализация здесь
https://github.com/leopro/trip-planner/blob/master/src/Leopro/TripPlanner/InfrastructureBundle/Repository/TripRepository.php
Вопрос: Как реализуете репозиторий если не используете Doctrine, Analogue, etc (т.е. ручками)?
Очень интересно как сохраняется сама модель и еще более интересно как связанные с ней. Например, у Trip есть Route, у Route - Leg и т.д. Как в таком их вытаскивать и сохранять, как работать с уровнем вложенности раз, два, три и т.д.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
возможно, всем кроме меня - ничего о TripPlanner не знаю
 

AmdY

Пью пиво
Команда форума
Вместо EntityManager ты можешь использовать Eloquent
 

Юрий Быков

Новичок
Вопрос скорее к адептам DDD, они наверняка его знают, так как во многих докладах этот пример участвует.
 

AmdY

Пью пиво
Команда форума
возможно, всем кроме меня - ничего о TripPlanner не знаю
Да это кусок говна на который молятся DDD-шники и в котором на каждом шагу костыли. Много раз на форуме проскакивал

Састливой отладки c*ки
https://github.com/leopro/trip-planner/blob/master/src/Leopro/TripPlanner/InfrastructureBundle/Repository/TripRepository.php#L21
https://github.com/leopro/trip-planner/blob/master/src/Leopro/TripPlanner/InfrastructureBundle/Repository/TripRepository.php#L32
 

Юрий Быков

Новичок
Да это кусок говна на который молятся DDD-шники и в котором на каждом шагу костыли. Много раз на форуме проскакивал

Састливой отладки c*ки
https://github.com/leopro/trip-planner/blob/master/src/Leopro/TripPlanner/InfrastructureBundle/Repository/TripRepository.php#L21
https://github.com/leopro/trip-planner/blob/master/src/Leopro/TripPlanner/InfrastructureBundle/Repository/TripRepository.php#L32
Касаемо первого в PHP 7.1 стало проще
public function get(TripIdentity $identity) : ?Trip
и можно отлаживать, да и сам интерпретатор ругнётся

По хорошему нужен метод require (помимо get), который возвращает именно объект и если его нет - Exception.

Если имелось что-то другое прошу расшифровать.
 
Последнее редактирование:

MiksIr

miksir@home:~$
Всё-таки больше интересно ручками кто-то делает? Свой разбор, sql, mapping.
В смысле "ручками"? Пишет свой датамапер? Ну есть и такие.
Но в общем ваш вопрос настолько абстрактен и бессмыслен, что и дальше будет собирать такие тупые ответы.
 

fixxxer

К.О.
Партнер клуба
Вопрос: Как реализуете репозиторий если не используете Doctrine, Analogue, etc (т.е. ручками)?
А зачем? Это сведется к написанию собственного датамаппера в итоге. Для этого нужны веские причины, а ты их не озвучил.
 

Юрий Быков

Новичок
Ну посмотри в исходники того же analogue (doctrine не предлагаю, там повеситься проще, чем разобраться ;))
За совет благодарю, смотрел Doctrine 2 года два назад, тогда было страшно, сейчас уже не так)
Doctrine 2.5 по мне более элегантный и функциональный нежели Analogue.
 

Юрий Быков

Новичок
Насколько понял из ответов, те кто использует паттерн "Доменная модель", пользуются готовыми ORM, те кто "Сценарий транзакции" - нативный SQL или ActiveRecord.
Получается в PHP (и вообще в языках с ООП) чтобы полностью следовать DDD вместе с SRP без ORM никак. Любой свой DataMapper переродится, в итоге, в тот же Doctrine и т.п. Если нам нужна скорость, то в любом случае придём к анемичной модели и к сценарию транзакций.
Прошу дополнить/исправить мой вывод, буду благодарен любой критике, подсказкам, советам.
 

Вурдалак

Продвинутый новичок
Получается в PHP (и вообще в языках с ООП) чтобы полностью следовать DDD вместе с SRP без ORM никак.
Необязательно.

Можно использовать event sourcing-модели (именно модели; это не подразумевает полный event sourcing на уровне инфраструктуры).

Пример будет выглядеть так:
PHP:
final class Trip
{
    public static function register(TripIdentity $identity, string $name): Trip
    {
        $trip = new self;
        $trip->apply(new TripWasRegistered($identity, $name));
        $trip->apply(new RouteWasPlanned($identity, 1, $name));

        return $trip;
    }

    private function onTripWasRegistered(TripWasRegistered $event): void
    {
        $this->id = $event->getIdentity();
        $this->name = $event->getName();
        $this->routes = [];
    }

    private function onRouteWasPlanned(RouteWasPlanned $event): void
    {
        $this->routes[$event->getRouteId()] = Route::create($event->getRouteName());
    }

    public function getEvents(): array
    {
        return $this->events;
    }
}
При сохранении в репозиторий, ты получаешь список записанных событий и либо используешь Doctrine/Eloquent для сохранения в более низкоровневую модель (которая просто представляется из себя пачку сеттеров/геттеров — прямо как в мануале), либо делаешь запросы напрямую:
PHP:
public funtion save(Trip $tip): void
{
    // $trip->getEvents()
}

private onTripWasRegistered(...): void
{
    // INSERT INTO trips VALUES ($tripId, $tripName, ...);
}

private onRouteWasPlanned(...): void
{
    // INSERT INTO routes VALUES ($routeId, $tripId, $routeName);   
}
 

Вурдалак

Продвинутый новичок
Но я должен сказать, люди очень большое значение придают тому, как должно сохраняться, в то время как к DDD это отношения по сути не имеет. DDD — это про модель, про устранение двусмысленностей с бизнесом, про bounded contexts. DDD это про ООП в модели. На самом деле, это просто ООП, про который мы просто почему-то тут же забываем, когда дело доходит по сущностей.

«Сеттеры и геттеры в модели, это же нарушение инкапсуляции, нет? Прямое противоречие с ООП?» — повторял программист, пока его никто не слышал. «Но ведь во всех мануалах так, все пишут так, значит я буду дураком, если выскажу это открыто».
 

Вурдалак

Продвинутый новичок
Да это кусок говна на который молятся DDD-шники и в котором на каждом шагу костыли.
Ничего себе у тебя бомбит. Это что-то личное?

Это какой-то недоделанный пример для какой-то презентации, что ты ожидаешь, что там не будет опечаток?
 

Юрий Быков

Новичок
Сеттеры не нужны, геттеры под потребности, но можно и без них, поддерживаю.
Вы используете event sourcing в реальных проектах и если да, то как часто, как влияет на производительность (entrprice тянет)? Если нет, то что используете?
 

Вурдалак

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