领域模型实例分析之-论坛

11-10-27 tangxuehua

说明:

1)上面的领域模型在设计时借鉴了DDD和CQRS的思想;

2)利用DDD的思想来设计实体、值对象、聚合、聚合根;图中有三个聚合根,分别是Forum、Thread、User;其中Thread聚合根聚合了Post和ViewCounter两个对象;Post是Thread的回复,显然Post离开Thread没有意义,但是Post在Thread聚合内有一个本地标识,即只要在当前Thread下唯一即可,不需要全局唯一。

3)由于CQRS思想的引入,可以确保我们在设计领域模型时不必考虑由于对象关联而产生的统计信息该如何存放,从而让领域模型更精简明了;如帖子的总回复数、最新回复时间、最新回复人,等等,这些信息只是统计信息,只用于在界面上显示,即我们只有在查询时才需要这些信息,因此可以在CQRS的Q端实现。

4)由于CQRS思想的引入,也可以让仓储更精简,不需要提供用于查询领域对象并在界面上显示结果的接口,而只需要提供用于查询单个聚合根或Add以及Remove的操作;

5)上面的领域模型只关注一个标准论坛的基本功能;

希望大家能多给些意见。之前学了很多的理论知识,现在是该通过一些建模例子锻炼一下的时候了。

[该贴被tangxuehua于2011-10-27 00:53修改过]

         

28
banq
2011-10-27 10:15

2011年10月27日 00:37 "@tangxuehua"的内容
图中有三个聚合根 ...

聚合根不能太多,Forum和Thread关系如同DDD一书中Car和Engineer的关系,用户User在当前上下文中应该服从与业务根。

tangxuehua
2011-10-28 12:36

我不清楚你所说的上下文是什么上下文。按照我的理解,如果我现在对一个论坛进行领域建模,那么上下文就是整个论坛。banq,你所说的上下文是指:论坛中的帖子模型的上下文、论坛用户模型的上下文、论坛版块模型的上下文吗?还是DCI中的场景?因为我把整个论坛定位为一个上下文,所以自己就认为有这么多主要的聚合根了,因为每个聚合跟在不同的业务场景下都有意义。

tangxuehua
2011-10-28 12:39

经过一些后续的思考后,我发现上面的领域模型中的帖子(Thread)的一些职责的设计有点问题。详细分析如下:

如果直接让帖子(Thread)维护回复(Post),那么当我们要添加一个回复时,必须把帖子的所有回复取出来,然后才能添加,这样势必会导致性能低下。本来依据信息专家模式,我们应该将添加回复的职责交给帖子来完成,但是因为遇到性能问题,我们必须考虑选择其他方案来即能在业务上保持帖子和回复的业务关系完整性,又不会有性能问题。

经过我的思考,我认为在ThreadRepository中完成这个职责比较合理。原因是:ThreadRepository是维护Thread的,因此它知道所有的Thread以及每个Thread聚合的内部细节,否则ThreadRepository无法对Thread进行持久化。所以,我们可以给ThreadRepository增加一个职责:AddThreadPost(threadId, post),该职责表示为某个帖子增加一个回复。AddThreadPost内部实现时不必先把Thread取出来到内存,而是可以直接操作关系数据库;依照这个推理,UpdatePost方法也可以这样实现;

我的这个解决方案如何呢?

tangxuehua
2011-10-28 12:41

从我上面的分析,大家有没有看到一个规律呢?那就是分析业务时,领域对象之间的关系并不代表在设计阶段必须在领域对象之间通过引用来表达,因为这很可能会导致性能低下,DDD告诉我们领域模型设计时不仅要考虑如何实现业务需求,也要遵循一些基本的软件设计原则以及性能方面的一些问题。实际上我认为领域对象之间的关系是从业务角度理解的一种业务关系,而在OO设计阶段并非一定要通过对象关联来表达这种关系,而可以采用其他替代方案但必须同样也要能表达业务关系。

从中我总结的规律是:

1)这种情况发生在1:N的时候;

2)当N这一端的明细项会在1这一段的对象之后逐步添加时;

3)N很大时;

这种情况下,我们往往需要采用上面的方案。

举个例子:

电子商务系统中,创建一个订单Order时,我们可以把Order的明细项OrderItem作为一个集合放在Order内,因为OrderItem总是和Order一起创建,不会在Order被创建后再逐步添加到Order中;

而在论坛中则不同,我们首先创建一个帖子Thread,然后回复会在Thread被创建后慢慢逐个增加,此时在当Post很多的时候,如果还是为Thread建立一个Post的集合的话,会导致性能低下。

[该贴被tangxuehua于2011-10-28 12:42修改过]

3Go 1 2 3 下一页