我目前正在研究一个由多个有界上下文组成的DDD系统。其中2个是:
问题在于:
登录到帐户管理上下文的用户根据定义是员工。所以我可以假设这里做出的改变是值得信赖的#34;在"意义上的数据被验证"。 appservice的简化版本如下所示:
class AccountAppService
{
public function changeAddress(string $accountId, string $address) : void
{
$account = $this->accountRepository->ofId(new Guid($accountId));
$account->changeAddress(new Address($address));
}
{
当员工更改地址时,这是我打电话的appservice。请注意,我没有注入/使用IdentityService来了解员工是谁,因为这在这里不是很有趣。在成功调用其changeAddress()方法后,Account实体将发出AccountAddressChanged事件
class Account implements Entity
{
public function changeAddress(Address $address) : void
{
$this->address = $address;
DomainEventSubscriber::instance()->publish(new AccountAddressChanged($this));
}
}
但是,一旦客户在网站上编辑数据,我也需要反映变化。我计划通过事件a" AccountAddressChangedViaWebsite"来执行此异步操作。帐户管理上下文将订阅并处理该事件,将相应的帐户设置为"未验证的"再次。因此,帐户管理上下文的简化订阅者可能如下所示:
class AccountAddressChangedViaWebsiteSubscriber
{
public function handle(AccountAddressChangedViaWebsite $event) : void
{
$accountId = $event->accountId();
$address = $event->getAddress();
$this->accountService->changeAddress($accountId, $address);
}
}
现在的问题是:员工通过订阅者直接呼叫appservice,客户。如果我们说"我们必须在客户更新其数据后重新验证帐户"这听起来像一个域名概念。 域概念适用于实体或域服务,但不适用于我所知道的应用服务或订户。这对我来说意味着应该避免以下情况(注意最后一行调用unverifyAccount()):
class AccountAddressChangedViaWebsiteSubscriber
{
public function handle(AccountAddressChangedViaWebsite $event) : void
{
$accountId = $event->accountId();
$address = $event->getAddress();
$this->accountService->changeAddress($accountId, $address);
$this->accountService->unverifyAccount($accountId);
}
}
这是一个隐藏在订阅者中的域逻辑,看起来很奇怪。我有直觉,这应该是域服务的责任,但域服务如何知道它是由外部事件(通过订阅者)或命令调用的?
我可以通过一种" Originator" ValueObject告诉我用户导致这是一个员工或外部系统。例如:
class OriginatorService
{
public function changeAddress(Originator $originator, Account $account, Address $address) : void
{
$account->changeAddress($address);
if(($originator instanceof Employee) === false) {
$account->unverify();
}
}
}
在这里,我将责任归咎于域名服务。但是可能将OriginatorService双重调度到Account实体是一个很好的解决方案吗?这样,实体可以通过询问传入的originatorService来检查导致更改的人,并且可以自己验证。
我想我会在这里找到DDD兔子洞,但在这种情况下你的经验/最佳做法是什么?
答案 0 :(得分:2)
最简单的答案可能是在您的模型中引入UnverifiedAddress作为一个概念,而不是试图处理"地址"作为一种普遍的想法,将验证作为事后的想法进行了抨击。