CQRS (Query & Command Multiple Buses) | Symfony PHP

Как реализовать CQRS подход в Symfony приложении, используя шины команд и запросов (Query & Command Multiple Buses).
Telegram: t.me/alejandroyakovlev
Уроки, менторство - boosty.to/sashokgorshok

Пікірлер: 60

  • @AlejandroYakovlev
    @AlejandroYakovlev5 ай бұрын

    Уроки, менторство - boosty.to/sashokgorshok

  • @user-sf5te2yj8w
    @user-sf5te2yj8w7 ай бұрын

    Очень познавательный урок, как и все остальные на этом канале. Хотелось бы больше видео.

  • @electrobayancheg
    @electrobayancheg Жыл бұрын

    Круто! Спасибо большое за работу 🙂👍

  • @vladislavlitvinov2790
    @vladislavlitvinov27902 жыл бұрын

    Круто, продолжай!

  • @fairy_tale1447
    @fairy_tale14472 жыл бұрын

    Спасибо! Ты молодец!!!

  • @super_mr_unknown
    @super_mr_unknown Жыл бұрын

    Спасибо за видео. Я уже давно работаю программистом, но как-то не встречал данный термин и заинтересовало, решил посмотреть. Подход интересный, чем то напомнило GraphQL с его query и мутациями, в плане разделения запросов на чтение и запись или выполнение команд. Единственное (предыдущие видео не смотрел, может там было объяснение) для новичков наверно не особо понятен принцип создания такой структуры приложения, нужно бы про domain driven design рассказать. Еще есть вопрос - если в микросервисе подразумевается наличие только команд, то есть все запросы это обратись к api и дай мне ответ что все окей или обратись к api и кинь в очередь сообщение что все окей. Вот в таком случае есть смысл использовать данный паттерн? Или это избыточно?

  • @maximsymfony
    @maximsymfony2 жыл бұрын

    Алехандро - уже 5 дней прошло - а вкусного видео до сих пор нет )))) Хотя в репо пару интересных вещей уже есть...... Ждемс

  • @AlejandroYakovlev

    @AlejandroYakovlev

    2 жыл бұрын

    Записал, монтирую, в скором времени будет на канале! Спасибо за поддержку! ))

  • @maximsymfony

    @maximsymfony

    2 жыл бұрын

    @@AlejandroYakovlev Если не секрет сколько лет, может и месяцев ты "шёл" к правильной архитектуре? Ты самоучка или хороший учитель был? Сколько у тебя лет опыта? P.s. Прости за то что тыкаю, просто мне кажется это более дружелюбно. Если ты против буду Выкать. Мне не сложно.

  • @AlejandroYakovlev

    @AlejandroYakovlev

    2 жыл бұрын

    В моём случае хорошие учителя были те, которые показывали как делать не надо :) Главный вопрос здесь, полагаю, не "сколько времени", а "каким образом". Ведь один человек за месяц может освоить то, что другой изучает годами. Здесь важны и условия и стимул. Безусловно нужен хороший ментор, который на голову выше во многих вопросах, не только технических. И в роли ментора хорошо выступают не только тех лиды, но и книги, статьи и видеоматериалы. Чтобы развиться в архитектурном направлении нужная хорошая почва для практики и разносторонний технический бэкграунд. У меня опыт разработки на данный момент 7 лет. Но вопросами архитектуры я занимаюсь только последние 3 года.

  • @user-rw3im8hr6z
    @user-rw3im8hr6zАй бұрын

    Спасибо большое за видео, но не очень понятно как с данным подходом реализовать непосредственно запись в одно место, а чтение из другого при наличии чистой архитектуры. Т.е у нас есть интерфейс репозитория где мы вызываем методы для чтения и записи, и на уровне юз кейсов мы не мыслим понятиями куда конкретно запишется и от куда конкретно прочитается. И получается, что если мы хотим иметь отдельное представление для чтения, то мы уже внутри конкретной имплементации репозитория реализуем запись в одно место, а чтение из другого и непонятно чем тут помогает разбиение на разные шины, если разделение логики чтения/записи происходит в репозитории. Мы фактически можем сделать тоже самое и без шин и разделения сервисов на команды и запросы. Выглядит так, будто разбиение на разные шины нужны просто чтобы визуально разделить друг от друга команды и запросы и возможность регулировать синхронность/асинхронность в них

  • @alexk6125
    @alexk6125 Жыл бұрын

    Ты бог!

  • @AlejandroYakovlev

    @AlejandroYakovlev

    Жыл бұрын

    Все мы боги :)

  • @disconnect3763
    @disconnect3763Ай бұрын

    Спасибо за видео. А что за приложение ты делаешь? Почему в браузере не показываешь? Мне очень интересно но не все понимают.

  • @AlejandroYakovlev

    @AlejandroYakovlev

    Ай бұрын

    В этом уроке еще не было конкретной тематики приложения. Позже в телеграм канале общим голосованием (t.me/alejandroyakovlev/15) было решено делать приложение по оценке навыков сотрудников.

  • @pitersolonovich1609
    @pitersolonovich1609 Жыл бұрын

    Очень круто, мне понравился подход CQRS в целом подход понятен и интересен. Вопрос с такими штуками как RabbitMQ и как это все использовать вместе и в каких случаях было бы очень интересно, особенно на примере микросервисного подхода, просто у меня не было опыта работы с сервисами очередей и вот то, что сделано в этом видео это по сути оно и есть?

  • @AlejandroYakovlev

    @AlejandroYakovlev

    Жыл бұрын

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

  • @user-rm6xt9gz2f
    @user-rm6xt9gz2f2 жыл бұрын

    Привет)) Видео класс. Как с тобой можно связаться по Event Storming?

  • @AlejandroYakovlev

    @AlejandroYakovlev

    2 жыл бұрын

    t.me/alex6ndr

  • @goqorgrigoryan4520
    @goqorgrigoryan452025 күн бұрын

    а потом удивляются зачем Ларавел стал популярным из всех

  • @StudioBaraban
    @StudioBaraban Жыл бұрын

    Привет, Саша, хочу задать тебе вопрос - Telegram не находит тебя - как с тобой связаться?

  • @AlejandroYakovlev

    @AlejandroYakovlev

    Жыл бұрын

    t.me/alex6ndr

  • @alexkamenskiy6118
    @alexkamenskiy61182 жыл бұрын

    1 - А почему ты в FindUserByEmailQueryHandler возращаешь UserDto, а не саму сущность User? 2 - И почему в конструктор CreateUserCommand не передать сразу готовую дто либо саму сущность? 3 - На каком уровне и где происходит логирование, допустим, такой пользователь уже существует UniqueConstraintViolationException, можно логировать в CreateUserCommandHandler?

  • @AlejandroYakovlev

    @AlejandroYakovlev

    2 жыл бұрын

    1. DTO более гибкая, и может содержать более широкий перечень свойств и в совершенно инос представлении. Плюс приитаком подходе сущность будет более защищенной от случайных мутаций. 2. Можно DTO передать, это особенно полезно, когда параметры в избытке. 3. На прикладном слое.

  • @user-yi5rk4ql8i
    @user-yi5rk4ql8i2 жыл бұрын

    Отличные видео. Но у меня вопрос - должен ли Command возвращать что-нибудь (тут возвращает) и почему в хендлер передается не "CommandInteface $command", а "CreateUserCommand" сразу

  • @AlejandroYakovlev

    @AlejandroYakovlev

    2 жыл бұрын

    Command по сути является DTO. Её хэндлер может возвращать результат работы: исключения, список ошибок, id созданной сущности. CreateUserCommandHandler на вход принимает команду, как раз таки реализующую CommandInterface.

  • @hackhawk307

    @hackhawk307

    Жыл бұрын

    @@AlejandroYakovlev когда команда возвращает ид созданной записи - это ломает суть асинхрнности cqrs. Правильнее было бы при создании юзера передавать заранее сгенерированный ид

  • @Zlobusz
    @Zlobusz Жыл бұрын

    Автор молодец, отличная демонстрация знаний работы месенджера, но считаю что тема совсем не раскрыта (и раскрыта не в тему). Нужен реальный пример из жизни, когда это стало бы необходимым. Плюс, CQRS как раз таки применяют для того, что бы доменный интерфейс репозитория не разбухал от методов вроде findByEmailAndRegisterDate() или findAllAndHereStarsOrderedByCreationDate($limit = 10)...

  • @AlexD-lc2nx
    @AlexD-lc2nx Жыл бұрын

    Damain? Шторм не ругался?

  • @fitter2boss72
    @fitter2boss722 жыл бұрын

    Если вы добавляете Пльзователю Profile , по какому полю вы их свяжите ulid int or ulid ulid? Хочу понять в User вы используете ulid из каких соображений, и вообще когда вы его используете? У ulid - есть минус, он не читаем человеком :) . Уроки хороши.

  • @AlejandroYakovlev

    @AlejandroYakovlev

    2 жыл бұрын

    Главнное преимущество в стравнении с INT auto increment , генерируеммым на стороне БД - это заранее известное значение идентификатора до записи в БД, которое позваляет строить агрегаты, отношения, генерировать события предметной области и пр. Поюс ulid уникальный в глобальном масштабе, что не скажешь о int, часто уникальный в пределах таблицы. Отношения вяжутся по ulid.

  • @fitter2boss72

    @fitter2boss72

    2 жыл бұрын

    @@AlejandroYakovlev А для Profiler (продолжая вопрос User Profile , One To One) Вы бы создавали свой ulid или сразу бы создовали с тем же , что и User?

  • @AlejandroYakovlev

    @AlejandroYakovlev

    2 жыл бұрын

    Однозначно свой ulid. Мухи отдельно, котлеты отдельно. Проще понимать структуру, когда идентификация сущности не зависит от внешних связей. Особенно если сущность со временем может превратиться в отдельный самостоятельный агрегат.

  • @leonidvasenin4041
    @leonidvasenin404110 ай бұрын

    Почему null но не исключение? Какой профит даёт бесконечное поднятие null? Чем плохо кинуть эксепшен из репозитория, ведь на уровне репозитория это исключительная ситуация, т.к. метод обещает (по названию) вернуть пользоователя, но не может этого сделать (по неизвестной причине).

  • @AlejandroYakovlev

    @AlejandroYakovlev

    10 ай бұрын

    Здесь вопрос удобства, места и времени. Попробуйте и так, и этак. В одном месте проще исключение кинуть, в другом null. В одном случае вам придется try catch обмазываться, в другом if. Где-то удобно контекст в исключении тащить, где-то в CommandResult. Вообще очень много нюансов. Действуйте по наитию.

  • @Vlad-hh1xk
    @Vlad-hh1xk11 ай бұрын

    Как CQRS реализовать Update в котором присутствует и чтение и запись?

  • @AlejandroYakovlev

    @AlejandroYakovlev

    11 ай бұрын

    В виде команды.

  • @RottenFoil
    @RottenFoil2 жыл бұрын

    Прежде всего скажу, что отличные уроки! А потом уже спрошу почему вы добавляете ключевое слово interface к интерфейсам, ведь это считается сейчас очень дурным тоном?

  • @AlejandroYakovlev

    @AlejandroYakovlev

    2 жыл бұрын

    Благодарю за отзыв! :) Если Вы о венгерской нотации, то она как лакарство - в малых дозах полезно, в больших - яд. Я являюсь противником избыточной информации в нейминге, если язык предполагает типизацию. Преимущества в случае с суффиксом Interface: 1. В Symfony так принято, если посмотреть на документацию. 2. Autocomplete в IDE при вводе Interface при создании класса через конструктор - лайфак, ускоряющий жизнь на несколько секунд. 3. Наглядность и определенность - мы явно видим, что внедряется интерфейс. Пробовал: Foo - интерфейс FooBarImpl - реализация. Тоже неплохо. В общем, как договоритесь в команде, так и делайте. Дело вкуса и удобства :)

  • @Zlobusz

    @Zlobusz

    Жыл бұрын

    Где это считается "очень дурным тоном"? Где-то считается, а где-то нет. Вопрос весьма спорный. Мне например норм сразу видеть, что это интерфейс (с суфиксом), кто-то любит в стиле C# обзывать с заглавной латинской i (например IUserRepository). Это чисто вкусовщина. Ой не туда вы замечания делаете, совсем не туда....

  • @user-kt8uj8wb5n
    @user-kt8uj8wb5n2 жыл бұрын

    всё очень классно, но очень тихо

  • @maximsymfony
    @maximsymfony2 жыл бұрын

    Спасибо, клёво. Вопрос 1) зачем нужны ДТО-шки. 2) Зачем так заморачиваться с папками Сущности в проекте? В другое место класть, в чем профит? 3) Смысл CQRS поняен, но то что ты сделал в Симфонии - реализация не очень.... 4) Ссылки пожалуйста добавь на Мартина Фаулера

  • @fitter2boss72

    @fitter2boss72

    2 жыл бұрын

    А вы не все видео посмотрели? Вроде в видео о архитектуре поясняется.

  • @maksimsalekseicevs3987

    @maksimsalekseicevs3987

    2 жыл бұрын

    @@fitter2boss72 честно, начал с конца как носподин Ютуб пожелал, дошёл до начала, и все равно это все мутно. Мы можем придумать вместо мопеда мотоцикл, он поедет быстрее, но архитектура все равно мопеда, просто рама потолще, да мотор с тормозами помощнее, в целом все тоже "колесо"

  • @fitter2boss72

    @fitter2boss72

    2 жыл бұрын

    @@maksimsalekseicevs3987 Для домашнего проекта эта архитектура оверхэд, но для сложных, где вам может быть понадобиться маштабируемость и микросервисы там это зайдет. Уже одно то, что бизнес логика может быть просто скопирована на другой фреймворк дорогого стоит. И еще добавлю, видео о домашних проектах "без" архитектуры (или с простой архитектурой) дофига, а о "взрослых" кот наплакал, я даже не вспомню никого, разве Дмитрия Е.

  • @AlejandroYakovlev

    @AlejandroYakovlev

    2 жыл бұрын

    1. DTO - для передачи данных, не более. 2. Сущности имеют прямое отношение к предметной области и находятся на слое, где эта предметная область представлена. 3. Опиши более конструктивно, что ты имеешь ввиду с примером альтернативной реализации. 4. Ссылки указаны в видео.

  • @maksimsalekseicevs3987

    @maksimsalekseicevs3987

    2 жыл бұрын

    @@fitter2boss72 все живут сегодняшним днем, тяп ляп и в продакшЭн. Платят же за то что работает, а не за правильную архитектуру )) я не приверженец RAD, просто если вокруг посмотреть, так и есть. Тем более я считаю Симфонию Enterprise Framework. Спасибо за разеснение, пожалуй копи пайсте папки в другой фрейм самый везкий аргумент.

  • @user-qx1jc9qv6h
    @user-qx1jc9qv6h Жыл бұрын

    А где юзкейзы? В чистой архитектуре они должны быть. Плюс в чистой архитектуре существует не гласное правило хорошего тона - метод, либо ничего не возвращает, либо должен вернуть ошибку, либо должен вернуть сущность. Это значит, что метод не должен возвращать null. И не важно, относиться этот метод к репозиторию, или к адаптеру, или же к сервису юзкейза. А отсюда соответственно следует, что ошибки бизнес логики - это ошибки, а не исключительные ситуации. То есть метод может вернуть либо ошибку, либо полезность, чаще всего сущность. В других языках для этого есть монады result или either, или есть возможность вернуть кортеж вида {result(:ok/:error), some_value}.

  • @user-sk1rh7yh7n
    @user-sk1rh7yh7n2 ай бұрын

    Почему-то в начале кажется, что гемороя с этими тестами больше чем от того с чем они призваны справляться :(

  • @user-kt8uj8wb5n
    @user-kt8uj8wb5n2 жыл бұрын

    Видео интересное. Но считаю, что интерфейс для репозитория не нужен

  • @Zlobusz

    @Zlobusz

    Жыл бұрын

    Еще раз прочитай про гексогональную архитектуру портов и адаптеров. Application Layer должен основываться на интерфейсах Domain Layer, а Infrastructure Layer хранит в себе реализации интерфейсов из Domain Layer. Попробуй вначале построить логику своего приложения исключительно на доктриновском репозитории и магических findBySomething, либо findBy(Criteria) или em->persist() em->flush(), а потом заменить DoctrineUserRepository на какой нить TarantolUserRepository, посмотрю я на тебя...

  • @alexeysitka
    @alexeysitka Жыл бұрын

    Всё круто, но о PSR при форматировании лучше не забывать. 😅

  • @olegs7470
    @olegs74705 ай бұрын

    Видео хорошее, но для новичков можно было бы объяснить CQRS без излишеств, а тут все зачем-то усложнено в 10 раз, и много лишнего. Вообще можно было все в три файла уместить.

  • @AlejandroYakovlev

    @AlejandroYakovlev

    5 ай бұрын

    Расскажите, пожалуйста, какие моменты считаете излишествами?

  • @user-yr9rq7we2n
    @user-yr9rq7we2n Жыл бұрын

    Нужно еще настроить БД для CQRS, чтобы запросы шли на слэйв, а комманды на мастер.

  • @Alexander-dg5id
    @Alexander-dg5id2 ай бұрын

    Удобство разработки?) Норм шутка)

  • @vladimir-v-
    @vladimir-v- Жыл бұрын

    Симфони отстой для недалёких.

  • @AlejandroYakovlev

    @AlejandroYakovlev

    Жыл бұрын

    Добро пожаловать

Келесі