我曾经参考ibatis的生成工具搞了一个叫example的东东,针对每个实体去设计可扩展的查询。可是我发现这种完全是针对数据库的方式来做的,查单表的时候不错,但我不认为是个好主意。我希望这个设计能脱胎于数据库去实现。
不知道各位有没有好的方式?
我曾经参考ibatis的生成工具搞了一个叫example的东东,针对每个实体去设计可扩展的查询。可是我发现这种完全是针对数据库的方式来做的,查单表的时候不错,但我不认为是个好主意。我希望这个设计能脱胎于数据库去实现。
不知道各位有没有好的方式?
使用CQRS将两者并存在不同领域中:读领域使用贫血模型,写领域使用充血模型,而非CQRS系统中,要么使用贫血模型贯穿读写,要么使用充血模型贯穿读写,都不方便。
在CQRS的读领域,你使用扁平的DTO来表达数据对象,无需Order里面含有OrderItem对象这么复杂,直接Order里面含有OrderItem的Id即可。
而在CQRS写领域,良好的Order包含OrderItem对象结构是一种聚合关系,一致对外,对内保持不变性,使用DDD加领域事件等等。
在CQRS的读领域,你使用扁平的DTO来表达数据对象,无需Order里面含有OrderItem对象这么复杂,直接Order里面含有OrderItem的Id即可。
而在CQRS写领域,良好的Order包含OrderItem对象结构是一种聚合关系,一致对外,对内保持不变性,使用DDD加领域事件等等。
===============================================================
我发现的确是这个问题,如果只用一个类是无法实现所有的设计组合,我碰到的一个真实的应用场景:
我们是一个互联网应用,图片、音频、视频为核心资源,为了方便用户使用,分别为这些资源进行分类,同时也给这些资源设计标签。
当时我的设计是这样的:
class Image {
private List
class Label {
}
后来发现,这种方式是非常错误的,因为会有从标签查找图片的需求。那么,我应该设计成以下这样吗?
class Image {
}
clss Label {
private List
}
发现还是不对,因为可能还有分页的需求。
那这样的设计肯定是有问题的。所以还是不对。
这两种设计其实代表两个方向的单向关联导航,前者可以根据Image查到Label,后者可以根据Label查到Image。
在写入这个场景中,比如修改,需要前者,那么Image一般是聚合根实体,而Label表示值对象,从DDD这个角度认识就自然肯定它们的主次导航关系。
而在读取场景,需要根据Label获得Image,是不是也要设计这种导航关系呢?当然不必,首先你是需要读取,可以直接通过仓储Repository获取,如果使用CQRS架构,直接通过SQL查询即可,比如根据Label的Id到Image数据表中查询(LabelId是Image的外键)。
[该贴被banq于2012-10-19 10:27修改过]
嗯,明白了,谢谢板桥的答复。
晕倒,读取的意思是各种报表分析,数据挖掘,或BI商业智能分析等等,这些都是针对现有业务逻辑产生的数据基础上再查询分析,因此和原来的业务逻辑不搭架的。
原来的业务逻辑通过CPU的算法都产生了数据,这些数据就是CQRS中Query用来分析的数据。
我把业务逻辑分解为:
场景 - 事件 - 状态 <===> 实体 - 聚合 - 领域
数据库中的数据就是状态,状态是事件产生的结果,也是实体的结果,这些都代表业务逻辑。
见:事件、契约设计与BDD
[该贴被banq于2012-10-19 17:28修改过]
这不是CRUD,CQRS中的Q是组织状态数据进行返回,就相当于“瞥一眼”就走了,而不是找谁谁谁来参与啥啥啥。这就很好区别“找实体集合”与“找数据集合”。因为我们运算基于业务逻辑,所以需要实体,但获取信息往往不是一整个实体,可能是部分字段,可能是字段变换值,甚至可能是统计值或期望值(与实体无关),其实就是一个“旁观者”(与“参与者”区别)。