领域驱动设计、仓储和混合实体

6

如果仓储库在构建过程中相互通信,是否违反了任何领域驱动设计原则?

例如,用户地址存储库与城市/地区/国家存储库交流以获取数据?

4个回答

14

我认为这违反了领域驱动设计的原则,仓库之间不应该相互引用。此外,仓库与数据库表之间也不应该进行一对一的映射。

这涉及到“聚合”和“聚合根”的概念。例如,假设数据库中有两个表:

Order
OrderLine

在1:n的关系中,(Order, OrderLine)被定义为聚合,因为OrderLine不能独立于Order存在。在这种情况下,Order是该聚合的根。

因此,不需要创建两个Repositories:

OrderRepository
OrderLineRepository
你只需要有一个OrderRepository来管理整个聚合,使用级联的加载、插入和删除操作来处理OrderLine。因此,在你的情况下,应该考虑是否存在地址/城市/地区/国家存储库。希望这可以帮到你。

2
除了我的系统中有些事情的处理方式之外,它确实有所帮助。我们已经标准化了省/州和国家。因此,如果用户或商店需要加载其地址数据并具有对区域/国家存储库将使用的表的引用。在这种情况下,加载不同版本的区域/国家是否可以?因为在这个上下文中,我将更多地使用它们作为值对象而不是实体。 - subliminal.one
1
谢谢您提供这么简单易懂的解释,我终于恍然大悟了。 :) - kman

1

针对您的问题,有几种方法:

  • 保持两个聚合根之间的紧密关系,并在第一个聚合根被填充时系统地填充第二个聚合根的整个聚合。这要求第一个存储库与第二个存储库通信,我认为这不会违反任何DDD原则,但可能会在性能方面存在潜在问题。

  • 将两个聚合根松散地链接在一起。这基本上意味着指向引用根的ID而不是完整实例。客户端代码或根本身(尽管有些人会说后者是不好的做法)将通过调用其存储库从其ID重新填充引用的根。

  • 认识到像城市、地区或国家这样的对象实际上是(不可变的)值对象,不需要ID,并且可以直接由任何聚合根或实体引用,而不会产生进一步的影响。这也意味着这些对象没有存储库。

选择选项1和2仅仅是技术问题,只会影响性能和开发人员的舒适度。选项3更多是一个领域选择,可能会产生业务影响。城市、地区和国家是用户能够创建、修改和删除的大型领域实体吗?是否有专门的屏幕用于这些?这些都是您在做出决策之前需要与领域专家讨论的问题。

以下链接可能会对您有所帮助:

聚合根引用其他聚合根

http://tech.groups.yahoo.com/group/domaindrivendesign/message/8696


0
在我们的系统中,我们遇到了与ISO货币和ISO国家相同的问题。我们发现几乎每个聚合根都需要货币和/或国家实体作为子实体(并且有相应的存储库)。从数据管理和检索的角度来看,这证明是低效的,因此我们采取了以下措施:
  1. 仍然保持每个聚合根只有一个存储库的概念(就像Cuong Le上面的答案一样)
  2. 维护国家和货币数据的缓存-当从数据库中提取聚合根时,我们使用缓存来检索货币/国家信息
从我的经验来看,DDD和蓝皮书是一份宝贵的指南,但您不必完全按照它,您可以采纳建议,然后适应自己的情况。
希望这能有所帮助...

0

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

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

相反,在数据库中创建一个视图,将用户地址与所有必需的信息一起加载(或者如果有 ORM 则使用它)。

总之:

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接