域驱动设计,存储库和混合实体

时间:2012-09-25 03:01:08

标签: repository domain-driven-design

如果存储库在构建期间相互通信,是否违反了任何域驱动的设计原则?

示例用户地址存储库与城市/地区/国家/地区存储库进行通信以获取数据?

4 个答案:

答案 0 :(得分:11)

它违反了域驱动设计,我认为,存储库不应该互相引用。此外,您不应该在存储库与数据库表之间映射1:1。

这是AggregateAggregateRoot的概念。例如,假设在数据库中有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国家相同的问题。我们发现,我们拥有的几乎所有聚合根(并且具有相应的存储库)都需要货币和/或国家实体作为子实体。从数据管理和数据检索的角度来看,这证明是低效的,所以我们做了以下事情:

  1. 仍然维护每个聚合根只有1个存储库的概念(如上面的Cuong Le的回答)
  2. 维护国家/地区和货币数据的缓存 - 当数据库中的聚合根耗尽时,我们会使用缓存来检索货币/国家/地区信息
  3. 根据我的经验,DDD和蓝皮书是一本非常宝贵的指南,但你不必100%准确地采用它,你可以在船上接受建议但是你可以根据它进行调整。

    希望这会有所帮助......

答案 3 :(得分:0)

好。 DDD中存储库的整个目的是抽象出数据源。如果您的用户地址需要完成城市/地区/国家/地区,请使用这些存储库。

该方法的问题在于查询效率相当低。

相反,在数据库中创建一个视图,用于加载包含所有必需信息的用户地址(如果有的话,还可以使用ORM)。

总结:

DDD中没有任何内容决定您应该如何实现您的存储库。 DDD非常清楚,无论信息如何存储在数据源中,从存储库加载的实体都应该是完整的= 存储库只是被定义为抽象层