请教关于DDD中,聚合根概念和相关实践的一些疑惑

13-04-05 tecentIDD9EEA
第一次在解道发帖,如果有什么不当的地方还请大家多海涵。

楼主最近在做一个网页社交游戏的开发,探索性地开了个分支版本,准备实践DDD。

在游戏中,会有以下概念:

玩家:即用户,拥有一个唯一的标识符,还有姓名、年龄等属性。

道具:游戏中虚拟的物品,比如蘑菇、鲜花之类的,同名的道具标识符是相同的。

背包:每个玩家有且仅有一个背包,背包里边包含50个格子,但可以通过付费增加格子。

背包格子:用来存放道具,一个格子中只能存放一种道具,但数量不限。

数据库方面我们选用的是MongoDB,目前为上述概念建模如下:

{

"_id":4f7180ccfcac61af7106236b, //玩家唯一编号,类型为MongoDB的ObjectId;

"name":"Player", //玩家姓名

"age":20, //玩家年龄

"inventory":{ //玩家拥有的背包信息;

"slots":[ //背包内包含的所有格子信息;

{"_id":1,"item":1,"qty":3} //单个格子的编号、物品编号、数量

...中间省略49个格子信息...

]

}

}

由于MongoDB的松散结构,为每个玩家建模起来也相当方便。但问题也随之而来:

1、把user作为聚合根,那么是否每次存取user的时候都必须把inventory加载进来?

游戏设计师:“我们要有一个页面,让当前登录的玩家看到和TA年龄相差3岁以内的玩家名字!”

其实只需要获得age字段即可了,加载inventory似乎没有必要。

2、如果必须把inventory也一同加载,那么当为user增加其他的属性的时候,会不会造成更大的查询性能浪费?

游戏设计师:“我们还要为每个玩家增加私人的农场,每个农场有50块田!偷菜游戏什么的最好了。”

模型上没什么问题,可以像inventory一样为user增加farm和farmUnit即可。但随着类似需求的增多,恐怕噩梦不远。

3、当加载inventory的时候,是否有必要保留一个对user的引用?

前两个问题我个人感觉可以用内存缓存解决,但是同时又会引入一个新的问题。

比如我们需要每隔一段时间将所有的玩家年龄+1,不使用内存缓存的时候可以直接使用请求命令。(如:db.user.update({},{$inc:{"age":1},false,true});)

可当使用缓存之后,由于部分玩家数据在缓存中,不能直接使用update命令对数据库进行更新。而遍历时又会把所有用户都加载到内存里,那就真成噩梦了……

使用延迟加载似乎是个好主意,但是目前官方驱动中并没有实现这种功能,实在纠结。

希望各位达人慷慨相助,再次感谢。

[该贴被tecentIDD9EEA于2013-04-05 00:19修改过]

         

banq
2013-04-05 10:45
懒赋值Lazy evaluation是一种更大意义上的懒加载,以区别于ORM那种可笑的虚假懒加载。

Lazy evaluation是函数语言的一个缺省功能,http://en.wikipedia.org/wiki/Lazy_evaluation

可参考JdonFramework使用事件EDA机制实现懒赋值:

EDA的懒赋值

这些都需要语言或者框架库包实现,属于底层基础设施,如果没有只能丑陋一点全部加载inventory,或者人为设计时根据不同加载需求切割inventory成很多小对象。

猜你喜欢