使用依赖注入实现聚合根之间调用的逻辑悖论

13-04-12 banq
DDD中如果有两个聚合根调用,如何解决?如果还是使用依赖注入,就会发生聚合根嵌套的可笑事情发生。

以代码为例子:有两个聚合根类AggregateRoot1 AggregateRoot2,AggregateRoot1的方法依赖AggregateRoot2实现,如果采取依赖注入,也就是Spring等框架做法如下:

class AggregateRoot1{
    AggregateRoot2 aggregateRoot2;

     public void dosth(){
       ....        
        aggregateRoot2.dosth();
      ...
    }
}
<p>

AggregateRoot1的dosth方法依赖AggregateRoot2的dosth方法,不自觉就将AggregateRoot2使用依赖注入,但是这样就造成了AggregateRoot1聚合AggregateRoot2的现象,AggregateRoot2还是聚合根吗?

什么是聚合?

class A{
   private B b;
   public B getB(){
      return b;
    }
}
<p>

这段代码表达了A聚合了B,也就是说整体A包含了部分B,A和B关系是父与子,整体与部分的关系。

我们使用这种聚合关系表达A是B的父对象,对于DDD聚合,如果A不再被其他对象引用,类似二叉树的一个根节点,那么我们认为A就是聚合根。

但是,因为依赖注入,我们破坏了业务上的聚合根概念。

那么两个聚合根之间相互调用怎么办?

只有通过事件。

[该贴被banq于2013-04-12 17:18修改过]

                   

17
brighthas
2013-04-12 19:08
呵呵!spring遇到DDD搞笑!两个思维模式,spring认为ioc能解决很多问题似的。

小秀一下寡人的框架JSDM 写aggre方式。

//  定义一个Aggre
function wrap(repos,services,publish){
     function A(){}
     A.prototype.fun = function(){
             var repo = repos.B; //得到B的repository
             repo.get("id001",function(err,b){
                   // 得到B的对象
                   ......
                  publish(发布事件)
             })
     }
     return A;
}

<p>

[该贴被brighthas于2013-04-12 19:08修改过]

clonalman
2013-04-12 20:53
class Order {
     Customer customer;
}
<p>

CRM、SupplyChain中Order、Customer 可都是聚合根

banq
2013-04-13 02:10
2013-04-12 17:16 "@banq

"的内容

那么两个聚合根之间相互调用怎么办?

只有通过事件。 ...

正是基于聚合根之间只能使用异步事件或消息,可能导致数据不一致性,Evans才发表文章:在聚合根实现CAP定理 Acknowledging CAP at the Root -‐-‐ in the Domain Model

认为聚合根之间遵循CAP定律,实现最终一致性即可。以前的讨论贴:聚合与一致性和有界上下文

聚合根存在于有界上下文,在上下文场景诞生并进行测试,如果两个聚合根通过直接引用,如上面roo1和roo2,则可能破坏它们各自所在上下文场景。

[该贴被banq于2013-04-13 02:13修改过]

tangxuehua
2013-04-13 12:27
1.聚合根之间通过ID关联即可,一个聚合根的任何一个操作不应该依赖于其他聚合根的信息或操作;

2.聚合根之间只能是最终一致性;

3.聚合根之间异步通信用event-driven architecture来实现;

4.saga,或ProcessManager就是用来实现这种异步通信从而实现最终一致性的一种技术;

5.采用event sourcing+in memory的架构模式让这一切更完美;

发现jdon上目前讨论saga或processmanager的帖子很少,但实际上要实现最终一致性,它们不得不提。

猜你喜欢
4Go 1 2 3 4 下一页