DDD 中聚合根的行为是否应该作为参与者?

Yur*_*kov 2 architecture entity domain-driven-design aggregateroot

我的英语不好,所以我举两个例子。在这个例子中,让我们从 DDD 中删除一些更重要的东西,主要是事情的本质。

如何从 DDD 的角度正确地做到这一点?

我们有两个聚合根,theSeller和 the Advert。在Seller可以编辑Advert这些例子:

1.

模型是否应该反映真实的业务逻辑?然后是Seller必须改变的人Adverts。即客户端层调用方法changeAdvertName()changeAdvertCost()聚合Seller。顺便说一下,这提供了访问检查等优势。我们可以看到Seller只能修改自己的Adverts. 这是第一个选项。

    //Client layer call seller.changeAdvertName(name)

    //AR Seller
    class Seller{
        adverts
        changeAdvertName(advertId, name){
            adverts[advertId].changeName(name)
        }
        changeAdvertCost(advertId, cost){
            adverts[advertId].changeCost(cost)
        }
    }

    //AR Advert
    class Advert{
        name
        cost
        changeName(name){
            this.name = name
        }
        changeCost(cost){
            this.cost = cost
        }
    }
Run Code Online (Sandbox Code Playgroud)

2.

另一种变体,客户端层可以直接调用方法changeNamechangeCost从聚合中调用Advert。我多次看到这个实现。

    //Client layer call advert.changeName(name)

    //AR Advert
    class Advert{
        name
        cost
        changeName(name){
            this.name = name
        }
        changeCost(cost){
            this.cost = cost
        }
    }
Run Code Online (Sandbox Code Playgroud)

您如何看待这些选项?它们都对 DDD
实现有效吗?从 DDD 的角度来看,哪个更正确、更合乎逻辑?

谢谢!

Voi*_*son 5

它们都对 DDD 实现有效吗?

领域驱动设计中的一个重要思想是一致性边界的概念——聚合是围绕状态的边界,可以单独修改——无需查看聚合之外的任何状态。

主要的好处是客户端代码不需要担心管理一致性规则;这种责任是综合性的。

另一个好处是对一个聚合的修改不需要阻止对另一个聚合的修改。

嵌套聚合根,通过让一个聚合持有对另一个聚合的引用,会使这个想法变得一团糟;试图修改广告的线程可能会干扰试图修改广告卖方的不同线程。

在单个聚合中拥有多个实体从根本上没有错。例如,您可以合理地将卖方实体和广告实体合并为一个卖方集合,并通过卖方对广告进行所有更改来强制执行一致性保证。然而,重要的是要认识到,在这个设计中,Advert 本身并不是聚合根。

让 Advert 成为它自己的聚合根并处理它自己的一致性规则也没有错,而卖方则生活在不同的聚合中。

在这个简单的例子中,卖家只是推迟对广告的更改,将它们彼此分开是有意义的,以便可以同时修改同一卖家的不同广告。

如果存在一些跨越多个广告的关键域不变量,那么您可能需要将它们全部拉入一个集合中,该集合可能存在于卖家集合中。

我的想法是,在实际的业务流程中,卖家专门创建广告并更改广告。但不是一个抽象的客户端层创建和更改广告。那么,请您帮忙理解一下好吗?

事实证明,在真实的商业世界中,卖家可以 create(),drop(),modify()... -> Advert。但是在 DDD 聚合中卖家只能实现 create(Advert) 行为?

这真的不是 DDD 特有的。它更多地反映了“面向对象”编程(如 Java 等所理解的)。行为——也就是说,状态的改变——通过向管理该状态的实体发送消息来发生。

面向对象的习语实际上与英语语法并不匹配。我们通常写“卖方修改广告”——一种主谓宾形式。但是在面向对象编程的语法中,对象会改变自己的状态以响应命令式时态消息(命令)。

List.addItem(...) - 我们没有修改列表,我们向列表发送了一个命令,上面写着:“修改你自己的状态”。

同样,卖家不会修改广告的状态;她正在发送一条消息,描述广告应该改变的方式,这取决于广告来做。

这是故意的:这意味着卖方可以与广告合作,而无需了解有关广告实施的任何信息,这意味着我们可以随时更换该实施而不会破坏卖方。