如果存储库在构建期间相互通信,是否违反了任何域驱动的设计原则?
示例用户地址存储库与城市/地区/国家/地区存储库进行通信以获取数据?
答案 0 :(得分:11)
它违反了域驱动设计,我认为,存储库不应该互相引用。此外,您不应该在存储库与数据库表之间映射1:1。
这是Aggregate
和AggregateRoot
的概念。例如,假设在数据库中有2个表:
Order
OrderLine
对于关系1:n,(Order,OrderLine)被定义为聚合,因为没有Order,OrderLine不能单独生存。在这种情况下,Order是此聚合的根。
有了这个,而不是创建两个存储库:
OrderRepository
OrderLineRepository
你应该只有一个OrderRepository
来处理整个聚合,使用级联加载,插入和删除OrderLine
因此,在您的情况下,应考虑是否存在地址/城市/地区/国家/地区存储库。
希望这个帮助
答案 1 :(得分:1)
您的问题有几种解决方法:
保持2个聚集根之间的紧密关系,并在第一根水合时系统地水合第二根的整个聚合体。这要求第一个存储库与第二个存储库进行通信,IMO不会破坏任何DDD原则,但在性能方面存在潜在问题。
松散地将两个根链接在一起。这基本上意味着指向引用的根ID而不是完整实例。客户端代码或根本身(虽然有些人会说后者是不好的做法)然后通过调用其存储库来重新水合引用的根。
认识到City,Region或Country等对象是真正的(不可变的)值对象,不需要ID,并且可以由任何聚合根或实体直接引用而不会产生进一步的后果。这也意味着没有这些对象的存储库。
选择选项1和2仅仅是一个技术问题,只会影响性能和开发人员的舒适度。选项3更多的是域选择,可能会对业务产生影响。用户可以创建,修改和删除City,Region和Country大域实体吗?是否有特别的屏幕专用于那些?在做出决定之前,您需要与领域专家讨论这些问题。
您可能会发现有用的链接:
Aggregate Root references other aggregate roots
http://tech.groups.yahoo.com/group/domaindrivendesign/message/8696
答案 2 :(得分:0)
我们在系统中遇到了与ISO货币和ISO国家相同的问题。我们发现,我们拥有的几乎所有聚合根(并且具有相应的存储库)都需要货币和/或国家实体作为子实体。从数据管理和数据检索的角度来看,这证明是低效的,所以我们做了以下事情:
根据我的经验,DDD和蓝皮书是一本非常宝贵的指南,但你不必100%准确地采用它,你可以在船上接受建议但是你可以根据它进行调整。
希望这会有所帮助......
答案 3 :(得分:0)
好。 DDD中存储库的整个目的是抽象出数据源。如果您的用户地址需要完成城市/地区/国家/地区,请使用这些存储库。
该方法的问题在于查询效率相当低。
相反,在数据库中创建一个视图,用于加载包含所有必需信息的用户地址(如果有的话,还可以使用ORM)。
总结:
DDD中没有任何内容决定您应该如何实现您的存储库。 DDD非常清楚,无论信息如何存储在数据源中,从存储库加载的实体都应该是完整的= 存储库只是被定义为抽象层