看来这个决定使对象充分认识到在系统中的角色,而且还避免了数据库具有域模型中太多的依赖,以及服务层?
例如:说我已经有了一个修订历史的实体,和几个"查找表"的数据引用,你的实体对象应该有方法从某些查找表获取详细信息,是否通过向提供接入查找表行,或通过将方法委托给它们,但为了做到这一点,它依赖于数据库层来从这些行读取数据.此外,当实体被保存时,它不仅需要知道如何保存自己,还需要知道将条目保存到修订历史中.是否有必要将对数十个不同数据层对象和服务对象的引用传递给模型对象?这似乎使得理解逻辑远比仅仅将薄模型传递给服务层对象要复杂得多,但我听到很多"聪明人"
真的很好问题.我花了很多时间思考这些话题.
通过注意表达域模型与关注点分离之间的紧张关系,您展示了很好的洞察力.这就像我在询问"不要问及单一责任原则"这个问题时的紧张.
以下是我对该主题的看法.
域模型是贫血的,因为它不包含域逻辑.其他对象使用贫血域对象获取和设置数据.你所描述的对我来说听起来不像是域逻辑.它可能是,但一般来说,查找表和其他技术语言很可能是对我们意味着什么的术语,但对客户来说不一定是什么.如果这不正确,请澄清.
无论如何,域对象的构造和持久性不应该包含在域对象本身中,因为这不是域逻辑.
所以要回答这个问题,不,你不应该注入一大堆非域对象/概念,比如查找表和其他基础设施细节.这是一个问题泄漏到另一个问题.域驱动设计中的工厂和存储库模式最适合将这些问题与域模型本身区分开来.
但是请注意,如果你没有任何域逻辑,那么你最终会得到贫血的域对象,即无脑的getter和setter,这是一些商店声称做SOA /服务层的方式.
那么你如何才能获得两全其美?如何将域对象仅关注域逻辑,同时保持UI,构造,持久性等不受影响?我建议您使用Double Dispatch等技术,或某种形式的受限方法访问.
这是Double Dispatch的一个例子.假设你有这行代码:
entity.saveIn(repository);
在您的问题中,saveIn()将拥有关于数据层的各种知识.使用Double Dispatch,saveIn()执行此操作:
repository.saveEntity(this.foo, this.bar, this.baz);
并且存储库的saveEntity()方法具有如何在数据层中保存的所有知识.
除了此设置,您还可以:
repository.save(entity);
只是打电话
entity.saveIn(this);
我重读了这个,我注意到实体仍然很薄,因为它只是将其持久性分配给存储库.但在这种情况下,实体应该很薄,因为您没有描述任何其他域逻辑.在这种情况下,你可以说"螺旋双重调度,给我访问者".
是的,你可以,但IMO它暴露了你的实体如何实现,而这些访问者是对域逻辑的干扰.我认为唯一应该有get和sets的类是一个名为"Accessor"的类.
我很快就会把它包起来.就个人而言,我不会使用saveIn()方法编写我的实体,因为我认为即使只是使用saveIn()方法也会使分散的域对象乱丢.我使用友元类模式,包私有访问,或者可能使用Builder模式.
好了,我完成了.正如我所说,我对这个话题非常着迷.