请教一个建模问题

11-04-12 pye
一个按照合同分期付款的需求,
现在我自己理解的划分:

实体:合同(聚合根),合同付款计划,合同付款核销记录
实体:客户(聚合根)
实体:付款记录(聚合根)

值对象:合同状态,属于合同

Service:核销

问题:客户可能拥有很多个合同,每个合同都有当月需要支付的款项,核销的时候必须将客户所拥有的合同的当月付款计划全部列出,然后排序获得应该核销的款项,并保留核销记录(可能有多条核销记录对应一条付款记录的情况,也会有一条核销记录对应多条付款的情况)。

我发现模型的聚合根如果是合同的话,对于核销Service来讲有可能要跨过合同聚合根,直接对合同付款计划进行访问,这违反了DDD的要求,会打乱对象的生存周期,但是如果把付款计划当作聚合根感觉付款记录好像跑到合同的上层去了,感觉怪怪的,大家指教一下吧。

另外,还有一些问题想问:
1. Service中能否不允许包含具体的业务知识,只能简单的操控对象来完成请求,此时理解为Service是大粒度的功能共享?
2. 一般大家都说只有聚合根才有Repository,那么对于聚合根内部的实体没有Repository的话,如何存取?直接在聚合根的getXXXList()方法里写数据库查询么?
3. 聚合根实体和聚合根内部的实体是否可以引用聚合之外的实体对象呢?

[该贴被pye于2011-04-12 12:42修改过]

1
banq
2011-04-12 14:19
2011年04月12日 12:40 "@pye"的内容
对于核销Service来讲有可能要跨过合同聚合根,直接对合同付款计划进行访问 ...


为什么要跨过合同聚合根呢?当然是通过合同聚合根再对其下的合同付款计划访问,不知道理由在哪里?

核销其实就是比对核查,看哪个合同已经付款,不涉及到合同怎么可以呢?

两个聚合之间可以发生关系,最好通过一个对象,也就是专门负责和外界打交道的对象。

两个聚合之间发生关系,一般都是和业务场景有关,象在核销这个场景下,合同和付款两个聚合要发生关系,但是你不能设计成静态的关联。
这个方式和请教banq老师一个repository的问题谈的场景差不多。

DDD太注重静态关系,具有ER或数据库建模的人虽然容易接受,但是因为都用静态关系去看待对象之间,好像没有看到场景和职责等动态关系。




pye
2011-04-12 14:45
因为在客户有多个合同的情况下,需要在其所拥有的所有合同中找到时间上最近的需要支付的付款计划,
概念如下:
客户1 -> contractA -> 4/13日付款
客户1 -> contractB -> 4/20日付款

跨过合同聚合根,直接访问查询支付计划然后按时间排序是最方便的方法,
是不是我应该在合同仓储里面实现这个排序的功能,然后返回合同,再经过合同访问付款计划呢?

banq
2011-04-12 14:49
使用Specification模式,给合同做个方法,get付款By日期,就是按照日期获得排序的需要付款集合,在这个方法中,你将排序的SQL作为规则或算法表达式封装起来,然后传到Repository内部进行运行,具体案例在DDD一书中Specification有讲解。

pye
2011-04-12 15:09
受教了,非常感谢。

猜你喜欢