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

Architecture DDD中聚合根的行为是否应该作为参与者?,architecture,entity,domain-driven-design,aggregateroot,Architecture,Entity,Domain Driven Design,Aggregateroot,我的英语不好,所以我举两个例子。在本例中,让我们从DDD中删除一些甚至重要的内容,主要内容是问题的本质 从DDD的角度来看,如何正确地做这件事 我们有两个聚合根,卖方和广告。在以下示例中,卖家可以编辑广告: 一, 模型是否应反映真实的业务逻辑。然后是卖家必须更改广告。即,客户层调用聚合卖方的changeardname()和changeardcost()方法。顺便说一下,这提供了访问检查这样的优势。正如我们所看到的,卖家只能修改自己的广告。这是第一个可能的选择 //Client layer

我的英语不好,所以我举两个例子。在本例中,让我们从DDD中删除一些甚至重要的内容,主要内容是问题的本质

从DDD的角度来看,如何正确地做这件事

我们有两个聚合根,
卖方
广告
。在以下示例中,
卖家可以编辑
广告

一,

模型是否应反映真实的业务逻辑。然后是
卖家
必须更改
广告
。即,客户层调用聚合
卖方
changeardname()
changeardcost()
方法。顺便说一下,这提供了访问检查这样的优势。正如我们所看到的,
卖家
只能修改自己的
广告
。这是第一个可能的选择

    //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
        }
    }
二,

另一个变体是,客户端层可以直接从聚合
广告
调用方法
changeName
changeCost
。我多次看到这个实现

    //Client layer call advert.changeName(name)

    //AR Advert
    class Advert{
        name
        cost
        changeName(name){
            this.name = name
        }
        changeCost(cost){
            this.cost = cost
        }
    }
你觉得这些选择怎么样?它们对DDD都有效吗
实施从DDD的角度来看,哪一个更正确、更符合逻辑

谢谢大家!

它们对DDD实施都有效吗

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

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

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

嵌套聚合根,通过让一个聚合包含对另一个聚合的引用,使该想法变得混乱;试图修改广告的线程可能会干扰另一个试图修改广告卖家的线程

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

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

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

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

我的想法是,在真实的业务流程中,具体来说,卖方创建广告并更改广告。但不是一个抽象的客户端层创建和更改广告。那么,你能帮我理解一下吗


事实证明,在真实的商业世界中,卖家可以创建()、删除()、修改()…->注意但在DDD聚合中,销售商只能实现创建(广告)行为吗

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

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

List.addItem(…)
-我们不是在修改列表,而是向列表发送一个命令,上面写着:“修改您自己的状态”

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


这是经过深思熟虑的:这意味着卖家可以与广告合作,而不需要了解广告的实现,这意味着我们可以随时更换该实现,而不会破坏卖家。

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

交易不应跨越聚合边界。要更新另一个聚合,请在单独的事务中使用域事件


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

谢谢!我的想法是,在真实的业务流程中,具体来说,卖方创建广告并更改广告。但不是一个抽象的客户端层创建和更改广告。那么,你能帮我理解一下吗?行为(方法)应该像抽象客户端层更改广告一样被调用?事实证明,在真实的商业世界中,
Seller
可以
create()
drop()
modify()
…-><代码>广告
。但在DDD聚合
中,卖家
只能实现
创建(广告)
行为?@YuryGolikov我会尽可能避免将行为放在主体实体上,除非出于创作目的。例如,
advert=seller.adverting(…)
但是
advert.end(seller)
…@plalx你能详细说明一下如何避免主体的行为吗?您是指聚合根操作的实体吗?@Tenek否,我只是指表示主题/角色(例如用户)的聚合。