Это видео недоступно.
Сожалеем об этом.

CQRS (Query & Command Multiple Buses) | Symfony PHP

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

Комментарии • 62

  • @AlejandroYakovlev
    @AlejandroYakovlev  8 месяцев назад

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

  • @user-sf5te2yj8w
    @user-sf5te2yj8w 9 месяцев назад

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

  • @electrobayancheg
    @electrobayancheg Год назад

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

  • @vladislavlitvinov2790
    @vladislavlitvinov2790 2 года назад +2

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

  • @fairy_tale1447
    @fairy_tale1447 2 года назад

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

  • @maximsymfony
    @maximsymfony 2 года назад

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

    • @AlejandroYakovlev
      @AlejandroYakovlev  2 года назад +1

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

    • @maximsymfony
      @maximsymfony 2 года назад

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

    • @AlejandroYakovlev
      @AlejandroYakovlev  2 года назад +1

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

  • @alexk6125
    @alexk6125 2 года назад

    Ты бог!

  • @super_mr_unknown
    @super_mr_unknown Год назад

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

  • @user-rw3im8hr6z
    @user-rw3im8hr6z 3 месяца назад

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

  • @Zlobusz
    @Zlobusz 2 года назад

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

  • @pitersolonovich1609
    @pitersolonovich1609 2 года назад

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

    • @AlejandroYakovlev
      @AlejandroYakovlev  Год назад +1

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

  • @disconnect3763
    @disconnect3763 3 месяца назад

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

    • @AlejandroYakovlev
      @AlejandroYakovlev  3 месяца назад +1

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

  • @StudioBaraban
    @StudioBaraban Год назад

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

  • @alexkamenskiy6118
    @alexkamenskiy6118 2 года назад +3

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

    • @AlejandroYakovlev
      @AlejandroYakovlev  2 года назад +1

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

  • @user-kt8uj8wb5n
    @user-kt8uj8wb5n 2 года назад +1

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

  • @fitter2boss72
    @fitter2boss72 2 года назад

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

    • @AlejandroYakovlev
      @AlejandroYakovlev  2 года назад +5

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

    • @fitter2boss72
      @fitter2boss72 2 года назад

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

    • @AlejandroYakovlev
      @AlejandroYakovlev  2 года назад +2

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

  • @maximsymfony
    @maximsymfony 2 года назад

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

    • @fitter2boss72
      @fitter2boss72 2 года назад +2

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

    • @maksims.alekseicevs
      @maksims.alekseicevs 2 года назад

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

    • @fitter2boss72
      @fitter2boss72 2 года назад +4

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

    • @AlejandroYakovlev
      @AlejandroYakovlev  2 года назад

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

    • @maksims.alekseicevs
      @maksims.alekseicevs 2 года назад

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

  • @user-yi5rk4ql8i
    @user-yi5rk4ql8i 2 года назад

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

    • @AlejandroYakovlev
      @AlejandroYakovlev  2 года назад +1

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

    • @hackhawk307
      @hackhawk307 Год назад

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

  • @AlexD-lc2nx
    @AlexD-lc2nx Год назад

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

  • @leonidvasenin4041
    @leonidvasenin4041 Год назад

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

    • @AlejandroYakovlev
      @AlejandroYakovlev  Год назад

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

  • @yashkevich8164
    @yashkevich8164 Месяц назад

    Не понял главного. Зачем мы это делаем?

  • @myks1992
    @myks1992 2 года назад

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

  • @Vlad-hh1xk
    @Vlad-hh1xk Год назад

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

  • @RottenFoil
    @RottenFoil 2 года назад

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

    • @AlejandroYakovlev
      @AlejandroYakovlev  2 года назад +2

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

    • @Zlobusz
      @Zlobusz 2 года назад +1

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

  • @user-qx1jc9qv6h
    @user-qx1jc9qv6h Год назад

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

  • @user-kt8uj8wb5n
    @user-kt8uj8wb5n 2 года назад

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

    • @Zlobusz
      @Zlobusz 2 года назад

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

  • @user-sk1rh7yh7n
    @user-sk1rh7yh7n 4 месяца назад

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

  • @olegs7470
    @olegs7470 7 месяцев назад

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

    • @AlejandroYakovlev
      @AlejandroYakovlev  7 месяцев назад

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

  • @user-yr9rq7we2n
    @user-yr9rq7we2n Год назад

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

  • @alexeysitka
    @alexeysitka Год назад

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

  • @Alexander-dg5id
    @Alexander-dg5id 4 месяца назад +1

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

  • @goqorgrigoryan4520
    @goqorgrigoryan4520 2 месяца назад

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

  • @vladimir-v-
    @vladimir-v- Год назад

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