DDD - 保持反向关系

DDD - Maintain inverse relation

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

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

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

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 组织包含有关就业的所有知识。最简单的解决方案是查询组织 table,但随后我在域层中引入了基础结构层。这违背了干净的架构原则(或我见过的其他 DDD 示例)。我可以引入一个执行业务逻辑的领域服务,但随后在领域服务中我可以查询组织 repository/service。尽管如此,领域层中仍然提到了基础设施层的一些东西。

问题:

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

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;
    }
}

只是对评论意见感到好奇:)

The simplest solution is to query the Organization table, but then I'm introducing a infrastructure layer in the domain layer.

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

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