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