【问题标题】:DDD - Maintain inverse relationDDD - 保持反比关系
【发布时间】:2021-10-18 18:42:06
【问题描述】:

我对聚合根 (AR) 之间的反比关系有疑问。当两个聚合根之间的关系已经确定时,即在某些操作之后,1-1 或 1-N 关系已被设置或更改。当您只允许更改一个聚合根时,逆关系如何知道它的存在。

我的问题是另一个聚合根使用的业务逻辑取决于聚合根之间的反向关系。

下面的代码是一个示例,因此使用的名称可能有点奇怪,但重要的部分是 AR 之间的关系。对于示例,我使用两个聚合根:人员和组织以及作为业务流程的就业。问题是行为只设置了关系的一侧。特此举例:

class Organization
{
    // parameter is a value object representing the Person AR.
    public function startEmployment(Person $person)
    {
        if (in_array($person, $this->employees)) {
            throw new Exception("Person is already an employee");
        }

        $this->employees[] = $person;
    }
}

通过上面的示例,我可以更改单个 AR,并且业务逻辑位于正确的位置。但是当我查看其他 AR 时,也就是 Person,我发现了一些麻烦的区域。例如,当业务要求是:人员在受雇期间不得改变居住地(可以想一个更好的例子)。

class Person
{
    public function changeLivingLocation(Location $location)
    {
        // what information and where do i get it from?
        if (...) {
            throw new Exception("May not change living location");
        }

        $this->livingLocation = $location;
    }
}

评论已经描述了问题。我从哪里得到信息? AR 组织包含有关就业的所有知识。最简单的解决方案是查询组织表,但随后我在域层中引入了基础设施层。这违背了干净的架构原则(或我见过的其他 DDD 示例)。我可以引入一个执行业务逻辑的域服务,然后在域服务中我可以查询组织存储库/服务。虽然,领域层中提到的基础设施层仍然有一些东西。

问题:

  • 当关系为 在另一个聚合根中确定?或者当聚合 root 需要一个聚合结果(例如,某个实体的计数)。
  • 当我在域层内时,如何从域外获取这些信息?

// 阅读第一个答案后更新 在阅读了答案并评估了存储库接口存在于域层中的想法后,我将其移至域服务。至少,对于我现在如何看待域服务。 我可以通过以下实现来评估 ij tun 基于存储库计数的业务逻辑。

class Person
{
    public function changeLivingLocation(MayChangeLocation $policy, Location $location)
    {
        if ($policy->evaluate ($this)) {
            throw new Exception("May not change living location");
        }

        $this->livingLocation = $location;
    }
}

class MayChangeLocation // effective the domain service
{
    public function __construct(RepositoryInterface $repository) {
        $this->repository = $repository;
    }

    public function evaluate (Person $person)
    {
        $organizations = $this->repository->getOrganzationsEmployesPerson($person->getId());
        
        // here real business logic is applied
        if (count($organizations) > 0) {
             return false;
        }
        return true;
    }
}

只是好奇评论 cmets :)

【问题讨论】:

    标签: domain-driven-design


    【解决方案1】:

    最简单的解决方案是查询组织表,但是我在域层中引入了基础设施层。

    这就是你应该做的,不是通过基础设施层,而是通过领域层中的查询

    您可以通过存储库来加载Person 中的Organization AR,或者使用服务,或者使用CQRS 术语中的Query

    【讨论】:

    • 在阅读了您的评论后,我让它沉入其中并提出了一个可能的解决方案。我很好奇你对此的看法。
    • 是的,这是一个好方法。只是一件事,如果您只是为此用例创建方法getOrganzationsEmployesPerson,或者您想要更高的性能,那么countOrganzationsEmployesPerson 方法会更好,因为您避免从数据库加载整个列表。
    • 当然了!谢谢!
    猜你喜欢
    • 1970-01-01
    • 2017-05-05
    • 2014-09-22
    • 2019-12-19
    • 2017-06-29
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多