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

Behavior of aggregate roots in DDD should be as actor or not?

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

如何从DDD的角度正确的去做?

我们有两个聚合根,SellerAdvertSeller 可以编辑这些示例中的 Advert

1.

如果模型应该反映真实的业务逻辑。那么必须改AdvertsSeller。即客户端层调用聚合 Seller 的方法 changeAdvertName()changeAdvertCost()。顺便说一句,这提供了访问检查等优势。我们可以看到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
        }
    }

2.

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

    //Client layer call advert.changeName(name)

    //AR Advert
    class Advert{
        name
        cost
        changeName(name){
            this.name = name
        }
        changeCost(cost){
            this.cost = cost
        }
    }

您如何看待这些选择?它们都适用于 DDD
执行?从 DDD 的角度来看,哪一个更正确、更符合逻辑?

谢谢!

Are they both valid for DDD implementation?

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

主要的好处是客户端代码不需要担心管理一致性规则;这种责任存在于总体中。

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

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

在一个聚合中包含多个实体基本上没有错。例如,您可以合理地将卖家实体和广告实体组合成一个单一的卖家聚合体,并通过让对广告的所有更改都经过卖家来执行您的一致性保证。然而,重要的是要认识到,在此设计中,Advert 本身并不是聚合根。

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

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

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

My idea was that, in the real business process specifically the Seller create Advert and change Advert. But not an abstract client layer create and change Advert. So, could you please help to understand?

It turns out that, in the real business world Seller can create(),drop(),modify()... -> Advert. But in DDD aggregate Seller can only implement create(Advert) behavior?

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

面向对象的成语实​​际上与英语语法不太匹配。我们通常写“Seller modifies advert”——一种主谓宾形式。但是在面向对象编程的语法中,对象会根据命令式时态消息(命令)改变自己的状态。

List.addItem(...) - 我们没有修改列表,我们正在向列表发送一条命令:“修改你自己的状态”。

同样,卖家没有修改广告的状态;她正在发送一条消息,描述广告应该如何改变,而这取决于广告。

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

聚合根是一致性边界,以确保域模型保持可靠状态。 我们从许多 DDD 从业者那里了解到这一点。

Transactions should, not cross aggregate boundaries. To Update another aggregate use domain events in a separate transaction. more

从这个角度来看,第二个选项会更有效,因为你有 2 个聚合根。