Domain driven design DDD:同步有界上下文导致不同的域行为/逻辑

Domain driven design DDD:同步有界上下文导致不同的域行为/逻辑,domain-driven-design,bounded-contexts,domain-events,Domain Driven Design,Bounded Contexts,Domain Events,我目前正在开发一个DDD系统,它由几个有界上下文组成。其中2项是: 上下文“帐户管理”:仅允许员工在此工作。其想法是管理客户账户(如地址、电话号码、联系人等),并验证客户账户(基本上是检查客户提供的数据是否有效) 上下文“网站”:我可以作为客户登录并编辑我的数据(例如更改我的地址) 问题是: 根据定义,登录到帐户管理上下文的用户是员工。因此,我可以假设此处所做的更改在“数据已验证”的意义上是“可信的”。appservice的简化变体如下所示: class AccountAppService {

我目前正在开发一个DDD系统,它由几个有界上下文组成。其中2项是:

  • 上下文“帐户管理”:仅允许员工在此工作。其想法是管理客户账户(如地址、电话号码、联系人等),并验证客户账户(基本上是检查客户提供的数据是否有效)
  • 上下文“网站”:我可以作为客户登录并编辑我的数据(例如更改我的地址)
  • 问题是:

    根据定义,登录到帐户管理上下文的用户是员工。因此,我可以假设此处所做的更改在“数据已验证”的意义上是“可信的”。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来了解员工是谁,因为这里对此不感兴趣。Account实体在成功调用其changeAddress()方法后将发出AccountAddressChanged事件,如下所示

    class Account implements Entity
    {
        public function changeAddress(Address $address) : void
        {
            $this->address = $address;
            DomainEventSubscriber::instance()->publish(new AccountAddressChanged($this));
        }
    }
    
    但我还需要在客户编辑网站上的数据时立即反映变化。我计划通过一个名为“AccountAddressChangedViaWebsite”的事件异步执行此操作。帐户管理上下文将订阅并处理该事件,并将相应的帐户再次设置为“未验证”。因此,帐户管理上下文的简化订户可能如下所示:

    class AccountAddressChangedViaWebsiteSubscriber
    {
        public function handle(AccountAddressChangedViaWebsite $event) : void
        {
            $accountId = $event->accountId();
            $address = $event->getAddress();
            $this->accountService->changeAddress($accountId, $address);
        }
    }
    
    现在的问题是:员工直接呼叫appservice,客户通过订户。如果我们说“我们必须在客户更新其数据后重新验证帐户”,这听起来像是一个领域概念。 域概念适合实体或域服务,但据我所知,不适合应用程序服务或订阅者。这对我来说意味着应该避免以下情况(请注意,最后一行调用unverifyAccount()):

    这是一些隐藏在订阅服务器中的域逻辑,看起来很奇怪。我有直觉认为这应该是域服务的责任,但是域服务如何知道它是由外部事件(通过订户)或命令调用的呢

    我可以传递一种“发起人”ValueObject,它告诉我造成这种情况的用户是员工还是外部系统。例如:

    class OriginatorService
    {
        public function changeAddress(Originator $originator, Account $account, Address $address) : void
        {
            $account->changeAddress($address);
            if(($originator instanceof Employee) === false) {
                $account->unverify();
            }
        }
    }
    
    在这里,我将做什么的责任委托给域服务。但是,将发起人服务双重分派到帐户实体中可能是一个好的解决方案吗?通过这种方式,实体可以通过询问传入的发起人服务来检查是谁导致了更改,并且可以自行取消验证


    我想我在这里要进入DDD兔子洞了,但在这种情况下,你的经验/最佳做法是什么?

    最简单的答案可能是在你的模型中引入未经验证的服装作为一个概念,而不是试图将“地址”作为一个普遍的想法,并将验证作为事后考虑。

    谢谢!这是有道理的,因为一个账户从来都不是整体验证的,而是部分验证的。不过,主要的问题仍然存在,因为applayer只从外部获取“原始”数据类型,所以永远不会“知道”您是否为其提供了验证过的地址。我想我会保持它的简单性,并且总是向域层提供一个未经验证的地址,并且用户必须在用额外的请求更新它之后进行验证。对于大多数用例来说,这应该足够了。
    class OriginatorService
    {
        public function changeAddress(Originator $originator, Account $account, Address $address) : void
        {
            $account->changeAddress($address);
            if(($originator instanceof Employee) === false) {
                $account->unverify();
            }
        }
    }