CQRS:在 CommandHandlers 中注入消息总线
CQRS : Injecting a messageBus in CommandHandlers
将整个总线注入 commandHandlers 以便后者可以调用 $this->messageBus->dispatch($events);
听起来是不是一种正确的方法
class OneCommandHandler
{
private $messageBus;
//.....
public function handle(Command $command)
{
//..... will at some points hopefully returns DomainEvents
}
private function dispatch(DomainEvents $events)
{
$this->messageBus->dispatch($events);
}
}
是不是耦合太大了?
只要你能把事情控制住;喜欢使用依赖注入框架或(未过度滥用的)服务定位器;我认为将总线注入域服务是可以的。
关于拥有存储库...添加另一层只是为了让域服务处于持久性无知状态怎么样?
我的意思是,如果OneCommandHandler
是应用域规则并触发域事件,则属于域服务层。域不应该有依赖关系。域应该应用规则和不变量并协调聚合的操作。所有这些都应该是域操作的输入参数。也许您需要应用服务层作为应用服务(安全、日志、持久性等)和领域服务的协调者。
即:
class ProductApplicationService
{
function ProductNameExchange($productExchangeComand){
LoggingAppService.LogAction("User ask to exchange product names");
SecurityAppService.AuthorizeCommand($productExchangeComand);
$productAggregate1 = ProductRepository.getProductById($productExchangeComand.firsProductId);
$productAggregate2 = ProductRepository.getProductById($productExchangeComand.secondProductId);
//rules and invariants
ProductDomainService.ExchangeNames($productAggregate1, $productAggregate2);
}
}
class ProductDomainService{
function ExchangeNames($productAggregate1, $productAggregate2)(){
//code to coordinate the 2 aggregates
$aux = $productAggregate1.name;
$productAggregate1.setName($productAggregate2.name); //$productAggregate has its own rules to change its name
$productAggregate2.setName($aux);
}
}
我什至会说这是推荐的,因为在您的命令处理程序中,您很可能想用处理状态回复发起者,唯一的方法是使用总线 reply/response 功能.
正如在 DDD/CRQS Google 组中讨论的那样,不存在 "one way (or "fire and forget") 命令",因为命令意味着动作、状态变化和这可能会失败,如果没有正确处理失败,系统将处于未定义状态,与幂等查询相比。
将整个总线注入 commandHandlers 以便后者可以调用 $this->messageBus->dispatch($events);
class OneCommandHandler
{
private $messageBus;
//.....
public function handle(Command $command)
{
//..... will at some points hopefully returns DomainEvents
}
private function dispatch(DomainEvents $events)
{
$this->messageBus->dispatch($events);
}
}
是不是耦合太大了?
只要你能把事情控制住;喜欢使用依赖注入框架或(未过度滥用的)服务定位器;我认为将总线注入域服务是可以的。
关于拥有存储库...添加另一层只是为了让域服务处于持久性无知状态怎么样?
我的意思是,如果OneCommandHandler
是应用域规则并触发域事件,则属于域服务层。域不应该有依赖关系。域应该应用规则和不变量并协调聚合的操作。所有这些都应该是域操作的输入参数。也许您需要应用服务层作为应用服务(安全、日志、持久性等)和领域服务的协调者。
即:
class ProductApplicationService
{
function ProductNameExchange($productExchangeComand){
LoggingAppService.LogAction("User ask to exchange product names");
SecurityAppService.AuthorizeCommand($productExchangeComand);
$productAggregate1 = ProductRepository.getProductById($productExchangeComand.firsProductId);
$productAggregate2 = ProductRepository.getProductById($productExchangeComand.secondProductId);
//rules and invariants
ProductDomainService.ExchangeNames($productAggregate1, $productAggregate2);
}
}
class ProductDomainService{
function ExchangeNames($productAggregate1, $productAggregate2)(){
//code to coordinate the 2 aggregates
$aux = $productAggregate1.name;
$productAggregate1.setName($productAggregate2.name); //$productAggregate has its own rules to change its name
$productAggregate2.setName($aux);
}
}
我什至会说这是推荐的,因为在您的命令处理程序中,您很可能想用处理状态回复发起者,唯一的方法是使用总线 reply/response 功能.
正如在 DDD/CRQS Google 组中讨论的那样,不存在 "one way (or "fire and forget") 命令",因为命令意味着动作、状态变化和这可能会失败,如果没有正确处理失败,系统将处于未定义状态,与幂等查询相比。