17

类似的问题可能已经被问过很多次了,但我认为每一个回答都有助于更好地理解 DDD。我想描述一下我如何看待 DDD 的某些方面。我对此有一些基本的不确定性,如果有人能提供一个可靠而实用的答案,我将不胜感激。请注意,这些问题假定了 DDD 的“经典”方法。这意味着使用 ORM 等。这里不考虑 CQRS 和事件溯源等方法。

  1. 聚合和实体是实现领域逻辑的主要对象。他们有状态和身份。在这种情况下,我将域逻辑视为改变该状态的所有命令的集合。那有意义吗?为什么域逻辑只与状态相关?对没有身份或没有状态的域对象进行建模是否合法?为什么不能将域对象实现为事务脚本?示例:考虑一个向您推荐约会网站合作伙伴的对象。那个对象没有真实的状态,但它做了很多领域逻辑?将其放入服务层意味着领域模型无法涵盖所有​​逻辑。

  2. 访问其他域对象。聚合可以访问存储库吗?示例:当(有状态)域对象需要访问系统的所有“用户”以执行其工作时,它需要通过存储库访问它们。因此,ORM 在加载对象时需要注入存储库(这在技术上可能更具挑战性)。如果对象无法访问存储库,您会将本示例的域逻辑放在哪里?在服务层?服务层不应该没有逻辑吗?

  3. 聚合和实体不应该与外界对话,它们只关心它们的有限上下文。我们不应该将外部依赖项(如 IPaymentGateway 或 IEmailService)注入到域对象中,这会导致域处理来自外部的异常。解决方案:基于事件的方法。那你如何发送事件呢?每次实例化域对象时,您仍然需要注入正确的“侦听器”。ORM 是关于恢复“数据”的,但主要不是为了注入依赖项。我们需要 DI-ORM 组合吗?

  4. 域对象和 DTO。当您查询聚合根的状态时,它是返回其状态 (DTO) 的投影还是域对象本身?在我看到的大多数模型中,客户端可以完全访问域数据模型,从而引入与域的实际结构的深度耦合。我认为聚合背后的“对象图”是它自己的业务。那是封装,对吧?所以对我来说,聚合根应该只返回 DTO。DTO 通常在服务层中定义,但我的方法是在域本身中对其进行建模。服务层可能仍会添加另一个抽象级别,但这是一个不同的选择。这是个好建议吗?

  5. 存储库在聚合根级别处理所有 CRUD 操作。其他查询呢?查询返回 DTO 而不是域对象。为此,存储库必须了解引入耦合的域的数据结构。我的建议与之前类似:使用事件来填充视图。因此,内部结构没有公开,只有事件携带必要的数据来构建视图。

  6. 工作单位。系统边界处的控制器将实例化命令并将它们传递给服务层,服务层进而加载适当的聚合并转发命令。控制器可能使用多个命令并将它们传递给多个服务。这都是由工作单元模式控制的。这意味着,存储库、实体、服务——都参与同一个事务。你同意吗?

  7. 业务逻辑不是领域逻辑。从业务角度来看,用例的实现可能涉及许多步骤:注册客户、发送电子邮件、创建存储帐户等。整个过程不可能适合域聚合根。域对象需要能够访问所有类型的基础设施。解决方案:工作流或 sagas(或事务脚本)。这是个好建议吗?

谢谢

4

2 回答 2

7

我可以建议的第一个最佳做法是阅读 Evans 的书两次
太多的“DDD 项目”失败了,因为开发人员假装 DDD 只是正确地完成了 OOP。

然后,您应该真正了解 DDD 适用于必须正确处理非常复杂的业务规则的应用程序。简而言之:如果您不需要支付领域专家来了解业务,那么您就不需要 DDD。实际上,DDD 的核心概念是编码人员、专家和用户共享以相互理解的无处不在的语言。

此外,您应该通过阅读Vernon 的 Effective Aggregate Design 来阅读和理解什么是聚合(一致性边界) 。

最后,您可能会发现此处记录的建模模式很有用。

于 2013-08-14T09:57:49.880 回答
6

尽管我在上面发表了评论,但我还是对你的观点进行了抨击。(注意:我不是 Eric Evans 或 Jimmy Nilsson,所以请对我的“建议”持保留态度)。

  1. 您的示例“考虑一个向您推荐约会网站合作伙伴的对象。”属于域服务(不是基础设施服务)。在这里看到这篇文章 - http://lostechies.com/jimmybogard/2008/08/21/services-in-domain-driven-design/

  2. 聚合不直接访问存储库,但它们可以创建一个工作单元,将来自多个域对象的操作组合成一个。

  3. 不确定这个。这本身应该是一个问题。

  4. 这是有争议的,理论上,域实体在聚合根之外不会直接可用,但这并不总是可行的。我会根据具体情况考虑这个决定。

  5. 我不确定您所说的“查询”到底是什么意思。如果在您的领域中对所有可能的“阅读”场景进行建模似乎不切实际或无法提供足够的性能,则表明 CQRS 解决方案可能是最好的。

  6. 是的我同意。UOW 是您工具箱中的一个工具,您可以在各个层中使用它。

  7. 这种说法从根本上是错误的“业务逻辑不是领域逻辑”。域是表示业务逻辑,因此使用ubiquitous language.

于 2013-08-13T20:26:19.997 回答