Command bus и CQRS

Yoskaldyr

"Спамер"
Партнер клуба
И думаю стоит заголовок у темы подправить что бы и CQRS и CQS. было в заголовке
 

Вурдалак

I'd like to model your domain
Просто если говорить об упрощенном CQS (без комманд баса и разделения на команду и хандлер), то кода получается в разы меньше и это проще использовать c другими одаренными разработчиками. Вот я и думаю как сделать с точки зрения кода, чтобы и писать было немного как при CQS, но был более менее полноценный CQRS.
Ошибочно полагать, что CQRS — это какое-то «расширение» CQS. Эти два слова только и роднит, что общее название. CQRS про модели, CQS про методы. Метод у command bus вполне может что-то возвращать, те же события. Некая идея о разделении «команд» и «запросов» роднит на очень далеком уровне. Под «командами» и «запросами» тут понимаются очень разные вещи.
 

Yoskaldyr

"Спамер"
Партнер клуба
да понятно что это не расширение. Я о том что в качестве примеров и в качестве более менее стандартных реализациях CQRS используются именно пары команда-хандлер, как результат инициализация громоздкая, да и много классов если применять как в примерах к библиотекам. Я чисто с технической стороны описания команды, а не о том какие модели будут использоваться под капотом.
Единый интерфейс для команд: с command id, без; требование context-объекта (что-то типа https://beberlei.de/2017/03/12/explicit_global_state_with_context_objects.html), возвращаемые значения (события, ошибки, etc.).
Я правильно понимаю, что есть только один класс команды куда передается контекст (в котором параметры для хандлеров) и id команды и команда может вернуть объект результата выполнения хандлеров и/или содержать массив ошибок их выполнения (типа $command->erros и т.д.)?
 
Последнее редактирование:

Yoskaldyr

"Спамер"
Партнер клуба
@Adelf @fixxxer А вы как используете command bus? Многословно как в мануалах? Т.е. по 2 и больше класса на команду (команда + хандлер минимум)? Или есть другие варианты?
 

fixxxer

К.О.
Партнер клуба
Ну да. А какие еще варианты? На php это немного задаблывает, да.

На Typescript вот так, чуток меньше писанины. (Сервисами, конечно, ничего не называю, disregard that).
 

Yoskaldyr

"Спамер"
Партнер клуба
Ну да. А какие еще варианты? На php это немного задаблывает, да.
Просто я вот думаю я правильно понял @Вурдалак насчет единой команды, куда параметры команды передаются через контекст, и с добавлением уникального команд ид или нет. И использует еще кто-то такое или нет. Просто такой подход значительно уменьшает количество почти идентичных классов команд, но я не уверен что правильно понял :)
 

fixxxer

К.О.
Партнер клуба
Ну не знаю, аргументы это аргументы, они у каждой команды свои. Терять типизацию и подсказки IDE ради непонятно чего?
А контекст - ну, да, так же как в миддлварях, не вижу разницы.
 

Yoskaldyr

"Спамер"
Партнер клуба
@fixxxer А такая идея имеет право на существование?
Т.к. в большинстве случаев у команды только 1 хандлер, объединять команду с хандлером в один класс, с возможностью добавления других хандлеров. Да я в курсе насчет нарушения SRP, но создавать отдельный класс из пары строк только для описания параметров - как-то перебор и явно не лучший код. Или использовать анонимный класс для команды.
 

Adelf

Administrator
Команда форума
@Yoskaldyr боязнь создания новых классов загубила немало кода.
Не надо бояться. Это вполне нормальная вещь для объектно-ориентированного программирования
 

Yoskaldyr

"Спамер"
Партнер клуба
Класс из 2 строк и только для описания параметров для хандлеров - это явно не самый лучший код
 

Yoskaldyr

"Спамер"
Партнер клуба
только проблема в том что dto-шки используются часто, а команда в 1 месте и все (в 99% случаев). Т.е. отдельная dto-шка только для единоразового использования - значит что-то не так с этой dto-шкой и передать данный можно было как-то иначе.

P.S. Да сюда прямо просятся анонимные классы, но только как самый последний вариант.
 

Yoskaldyr

"Спамер"
Партнер клуба
уточняю. я имею ввиду дто-шку для передачи данных не просто в пределах одного слоя (а не между слоями), а в пределах одного класса.
Т.е. это полный аналог, если писать
PHP:
class SomeUser {
//   и конструктор присвающий эти значения, лень писать
    public $name;
    public $email;
}
//.....
class SomeClass {

public function someMethod () {
// создание этого класса только в этом месте и все, больше нигде в коде встречаться не будет
    $user = new SomeUser ('User Name', 'foo@domain.com');
    $this->userMethod($user);
}

public function userMethod (SomeUser $user) {
//    делаем что-то в почтой и именем
//   но метод вызывается и используется только один раз в $this->someMethod и это 100% известно что не будет меняться
}
}
вместо более простой версии
PHP:
class SomeClass {
public function someMethod () {
    $this->userMethod('User Name', 'foo@domain.com');
}

public function userMethod ($name, $email) {
//    делаем что-то в почтой и именем
//   но метод вызывается и используется только один раз в $this->someMethod и это 100% известно что не будет меняться
}
}
Какой сакральный смысл в такой дто-шке? Только для обмазывания паттернами?
 
Последнее редактирование:

Adelf

Administrator
Команда форума
этот пример вообще непонятен. я думал мы говорим про Command классы в контексте Command bus.
Data Transfer Object. дтошки делаются для трансфера данных куда-то. например эту команду могут послать выполнить не сразу, а в очереди. абстракция комманд баса дает некоторые преимущества...
 

Yoskaldyr

"Спамер"
Партнер клуба
абстракция комманд баса дает некоторые преимущества...
Я то понимаю все плюсы, проблема в том что когда известны поставленные задачи и заранее известно, что 90% всех команд будут из команды и одного хандлера и никаких отложенных выполнений, никаких очередей и т.д. А остальные 10% будут для добавления дополнительного логирования через еще один дополнительный хандлер. Все.
Зачем заранее усложнять если ничего сложного заранее известно что не будет?
 
Последнее редактирование:

Yoskaldyr

"Спамер"
Партнер клуба
А мой пример в том что в некоторых случаях пачки пар команда + хандлер выглядят точно как в примере, т.е. разовое использование класса и только для передачи параметров в единственный хандлер.
 

AnrDaemon

Продвинутый новичок
У тебя в приложении всего одна команда с единственным параметром?
 

Yoskaldyr

"Спамер"
Партнер клуба
У тебя в приложении всего одна команда с единственным параметром?
Еще раз попытаюсь объяснить. У меня куча команд с разными параметрами. Но 90% из них это команды из одного хандлера, который используется только в этой конкретной команде.
Я понимаю все преимущества небольшого класса команды (дто) в комманд басе - можно хранить, сериализировать передавать на другие микросервисы и т.д.
Но если этого не будет и в принципе не может быть исходя из поставленных задач и если почти всегда только один уникальный командхандлер на конкретную команду. Тогда зачем делать
PHP:
(new SomeCommand($param1, $param2))->registerHandler(new SomeCommandHandler())->exec();
если можно сделать
PHP:
(new SomeCommandWithIncludedHandler($param1, $param2))->exec();
И в случаях когда надо больше одного хандлера (меньше 10% всех команд)
PHP:
(new SomeCommandWithIncludedHandler($param1, $param2))->registerHandler(new SomeCommandSecondHandler())->exec();
Т.е. мне из CQRS почти не нужен комманбас, нужно разделение на команды и квери и разделение на рид и райт модели.
 

Yoskaldyr

"Спамер"
Партнер клуба
Еще раз повторюсь что я понимаю что тут есть нарушение SRP, но это только как компромисс.
 
Сверху