这是一个老问题,你可能以某种方式解决了这个困境,但我会试着回答它。
你写了:
“只有来自帐户有界上下文的 id、全名、电子邮件和头像等信息与工作有界上下文相关”
它们真的与 Job BC 有关吗?使用实体(甚至更多:使用聚合)您是在建模流程,而不是数据。在 Job BC 的哪个流程或用例中需要全名?该领域是否有规定不得雇用具有特定名字或姓氏的人?我假设不是。这么说你可能想到了,你必须显示一些屏幕,其中显示了一个人的全名。但屏幕不是流程,它们只是报告。您不应该通过报告/屏幕/UI 来驱动您的模型,而应该通过特定域中存在的流程来驱动您的模型。
好的,但是怎么做呢?显然,您仍然需要生成一些报告/屏幕。不是吗?答案是:您需要 CQRS ( https://martinfowler.com/bliki/CQRS.html )。命令堆栈只是聚合等达到的流程模型。因此,您的构建块将由一些 ORM 持久化。它们的数据模型将由它们(构建块)的外观驱动。在这里使用一些可以轻松持久化甚至复杂聚合的 ORM,例如 Hibernate。
然后你必须建立查询堆栈。我看到了两种实现它的方法,它们取决于您是否在同一个数据库模式中拥有两个 BC。
当两个 BC 位于同一架构上时,只需使用一些数据库视图来为您的报告/屏幕构建数据。在这里使用一些非常快速和灵活的复杂查询 ORM,例如 MyBatis 或 Spring JDBC(如果您想与 JDBC 愤怒斗争,甚至可以使用普通 JDBC ;))。如果不是迫不得已,不要在这里使用 Hibernate,因为您会发现在这个堆栈中尽可能接近 SQL 是很好的。数据查询抽象将迫使您努力使用框架/ORM 来实现由聚合及其流程驱动的数据模型的复杂连接,而不是屏幕。另一个原因是,在普通的业务应用程序中,读取比写入 DB 多几个数量级,在 CQRS 中,查询堆栈的使用量比命令堆栈的使用量多,所以你需要快速的东西。
当 BC 使用不同的模式时,您需要构建报告数据库 ( https://martinfowler.com/bliki/ReportingDatabase.html ),它将“合并”两个模式。然后您可以对合并模式进行查看,问题简化为上述问题。
请注意,报告数据库为您提供了另一种扩展可能性:该数据库是只读的,因此可以在多个服务器之间轻松复制,您的查询堆栈服务可以成倍增加并隐藏在一些负载均衡器后面。
好的,但是电子邮件地址属性呢?您的域中可能有一个用例,应通知雇主或申请人在域上执行的某些操作/流程。我认为处理此用例的域服务(或域事件处理程序)应该向其他 BC 的服务询问此特定用户的电子邮件(或广播将在某处处理的域事件)。甚至更好 - 它应该将这项工作委托给另一个 BC 中的某个通知服务。此通知服务将向帐户 BC 的服务询问电子邮件地址。
在我看来,限界上下文(连同通用语言)是 DDD 最重要的思想。这是在建模过程中避免大泥球的真正强大工具。而且在实际领域中确定限界上下文真的很不容易:)