浅谈值对象
关于值对象的概念请参考ddd
值对象是用来描述实体的,比如基元类型,完整概念(Whole Value)[货币、XXX类型、角色、XXX类别、枚举]等等。
因为数据关系模型与领域模型,存在着隔阂,也就导致领域对象在关系数据库中的存储发生变化,所以通常来说都需要做映射
如果领域实体中存在Whole Value的值对象,因为值对象可以共享,所以可能将Whole Value单独建表,但是
在《企业应用架构模式》[Martin]中(嵌入值)和《ddd》中都建议采用非规范的做法,他们的理由是在读取数据时就不需要跨页,而且为一个
值对象提供全局查询没有意义 也许在某些情况下 确实没有意义,我也一直是这么做的。
但是有些时候确实需要,比如查询的时候需要列出所有的XXX类型,因为这些XXX类型可能会有添加,你可能会想(值对象不是不变的吗)
如果这么死板的话,就可能每次改变都需要找出代码来重新编译,重新部署。人家直接拼sql的人根本就不需要这样做,完全不考虑什么实体、
值对象。那我们采用ddd却不允许这样,这难道是ddd的缺陷
当然建议归建议,也不必这么生搬硬套,所以还是具体情况具体考虑,需要单独建表就单独建表。
解决了上面的问题,引来了下面的问题
值对象既然需要提供全局查询,那么这个职责有谁来承担?
这个问题在《ddd》和《企业应用架构模式》书中都没有给出什么解决方法。
思考过的两种方法:
1.由值对象相关的实体的仓储来承担,但是问题依然麻烦(比如有些值对象,它可以被不同实体使用,那到底放在哪个上呢?)
2.有单独一个'值对象仓储'来承担,但感觉职责过载,最要命的是感觉这个仓储是无中生有。
.NET Domain-Driven Design with C#: Problem-Design-Solution书的作者Tim采用的方式,就是我提的第一种方法。也许第一种比第二种稍好
这段时间在用EF和Ado.net Data Service,说实话 EF真的不适合 用在ddd中,EF本身不支持值对象,而且要命的是模型从数据库推出来
而且你不得不受EF的限制,导致在代码中到处都有ObjectContext的身影。
以前ms把数据库暴露到控件,这次更疯狂了,直接暴露到url上,尤其EF跟DataService结合的如此紧密,要实施ddd简直就是痛苦至极。
我们公司有人以前做的DataService只不过做了下url的route并调用相应的method,非常方便。