Domain driven design 你能推荐DDD的最佳实践吗

Domain driven design 你能推荐DDD的最佳实践吗,domain-driven-design,Domain Driven Design,可能类似的问题已经被问了很多次,但我认为每一个回答都有助于让人们越来越了解DDD。我想描述一下我是如何看待DDD的某些方面的。我有一些基本的不确定因素,如果有人能给出一个坚实而实用的答案,我将不胜感激。请注意,这些问题假设DDD采用“经典”方法。这意味着使用ORM等方法。这里不考虑CQR和事件源等方法 聚合和实体是实现域逻辑的主要对象。他们有国家和身份。在此上下文中,我将域逻辑视为所有改变该状态的命令集。这有意义吗?为什么域逻辑只与状态相关?对没有标识或没有状态的域对象建模合法吗?为什么域对象不

可能类似的问题已经被问了很多次,但我认为每一个回答都有助于让人们越来越了解DDD。我想描述一下我是如何看待DDD的某些方面的。我有一些基本的不确定因素,如果有人能给出一个坚实而实用的答案,我将不胜感激。请注意,这些问题假设DDD采用“经典”方法。这意味着使用ORM等方法。这里不考虑CQR和事件源等方法

  • 聚合和实体是实现域逻辑的主要对象。他们有国家和身份。在此上下文中,我将域逻辑视为所有改变该状态的命令集。这有意义吗?为什么域逻辑只与状态相关?对没有标识或没有状态的域对象建模合法吗?为什么域对象不能实现为事务脚本?例如:考虑一个对象,建议你约会网站的合作伙伴。这个对象没有真实状态,但它有相当多的领域逻辑?将其放入服务层意味着域模型不能覆盖所有逻辑

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

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

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

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

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

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


  • 谢谢你

    尽管我发表了上述评论,但我还是尝试了你的观点。(注意:我不是埃里克·埃文斯或吉米·尼尔森,所以对我的“建议”持保留态度)

  • 您的示例“考虑一个向您推荐约会网站合作伙伴的对象”。属于域服务(而不是基础设施服务)。请参阅本文-

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

  • 我不确定这件事。这本身应该是一个问题

  • 这是有争议的,理论上,域实体在聚合根之外不会直接可用,但这并不总是可行的。我在逐案的基础上考虑这个决定。

  • 我不知道你所说的“询问”到底是什么意思。如果在您的领域中对所有可能的“阅读”场景进行建模似乎不实用或不能提供足够的性能,那么这表明CQRS解决方案可能是最好的

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

  • “业务逻辑不是域逻辑”这句话从根本上是错误的。域是业务逻辑的表示,因此使用
    泛在语言
    的原因之一


  • 我能建议的第一个最佳实践是两次
    太多的“DDD项目”失败是因为开发人员假装DDD仅仅是OOP做得对

    然后,您应该真正了解DDD适用于必须正确处理非常复杂的业务规则的应用程序。简言之:如果你不需要私人助理