我的观点是:
1)Repository接口的输入参数或返回参数应该是聚合根,而不能是聚合内的某个实体;
2)如果Repository接口的参数可以随便设计,那Repository已经和DAO五差别了,这其实就是把Repository当作DAO来用了,纯粹是把他当作是一个更新数据或去数据的接口了。而实际上DDD中的Repository面向的一定是聚合根,就是指接收的参数或返回的都应该是聚合跟;这样才符合Repository是一个生活在内存中的集合的定义;
3)在Order类中访问Repository是不可取的;我极不赞成这样的做法;而基于事件驱动的思路我比较赞同;Domain Object的职责是告诉别人我发生了什么即可,而不能去请求别人我要做什么,比如请求Repository帮他把某个OrderItem给持久化一下;
4)再给你举个列子说明一下为什么不能只保存聚合的部分实体;比如一个订单,目前最多只能容下最多一个OrderItem了,然后A,B两个人同时取出这个订单,这是对于A,B来说,他们都知道还能再新增一个OrderItem,于是他们先后新增了一个OrderItem,当A新增一个OrderItem时,数据库锁住Order,然后更新成功,解锁;然后B新增了一个OrderItem,数据库再锁,然后保存成功,然后解锁;为什么后面的OrderItem也能保存成功?因为数据库是不具备业务逻辑去判断当前这个OrderItem能否被新增的,只有内存中的Order才知道;数据库只能确保不能有两个人同时改同一个Order;基于上面的情况,数据库最后就会出现一个Order包含了过多的OrderItem的情况,从而也就违反了不变性约束;
5)从逻辑的角度,你想想你希望一个东西的状态不能违反某个不变性,但是允许多个人以先后的顺序在不同的内存空间部分的添加或删除其子实体,并且可以允许部分持久化;要知道数据库是不具备聚合所规定的不变性约束规则的,它只知道帮你锁数据,或者接收新的数据而已;只是一个帮你管理数据的容器;再强调一次Aggregate is a unit of data changes,要做到unit,不只是在内存中要通过聚合的方式来控制,也需要在数据库中也确保其被更新时是以一个整体的姿态被更新的,而不能只更新部分;那么因为数据库里没有所谓的聚合的概念,那如何确保数据库里某些实际上是“聚合”数据也能作为一个单元被更新呢?只有一个办法,那就是任何人更新这些数据时,都是完整替换,而不是部分替换;从而才引出为什么整个聚合要整个完全覆盖数据库里的数据的原因。
2011年12月29日 18:55 "@qiuriyuchen"的内容
终于知道我在说什么了,哈哈,这正是我想和你讨论的呀,我的意思就是没有必要全部一起保存,部分保存就可以了。先说在单机程序中吧,如果客户端持有的是副本,我觉得可以像这样order.EditOrderItem(orderItem),因为order ...