Domain driven design 域驱动器设计与命令模式&x2014;相互排斥?

Domain driven design 域驱动器设计与命令模式&x2014;相互排斥?,domain-driven-design,command-pattern,Domain Driven Design,Command Pattern,tl;博士: 我喜欢命令模式的小型集中类,如SetProjectAsActiveCommand,但我也喜欢DDD让模型负责自己的核心业务功能的方法,如调用Project::setAsActive()这两种想法可以一起工作,还是它们是相互排斥的体系结构? /tl;博士 在过去的几个月里,我一直在做一个项目,在这个项目中,我们一直在使用命令模式,它有像ProposeNewProjectCommand,SetProjectAsActiveCommand和AddCommentToProjectComma

tl;博士:
我喜欢命令模式的小型集中类,如
SetProjectAsActiveCommand
,但我也喜欢DDD让模型负责自己的核心业务功能的方法,如调用
Project::setAsActive()
这两种想法可以一起工作,还是它们是相互排斥的体系结构?
/tl;博士

在过去的几个月里,我一直在做一个项目,在这个项目中,我们一直在使用命令模式,它有像
ProposeNewProjectCommand
SetProjectAsActiveCommand
AddCommentToProjectCommand
这样的类,所有这些类都由命令总线处理。这些课程往往相当小,而且集中精力,只做一件事

最近我一直在阅读关于域驱动设计(DDD)的文章,我认为这种方法更依赖于模型本身的工作,因此上面的命令可能会被
organization::proposeNewProject()
Project::setAsActive()
Project::addComment()
所取代

在模型上使用这些方法意味着它们可以充当“聚合根”(例如,在上面的示例中,
Project
负责创建自己的注释)

虽然我真的很喜欢让我的实体对其核心业务功能承担更多责任的想法,但我也担心我的模型可能会变得非常非常大,因为它们上面有许多与应用程序可以做的各种事情相关的方法

有没有一种方法可以让命令模式的小型、集中的类同时仍然让模型成为一流的公民,负责其关键业务功能,如DDD?还是解决潜在大模型问题的方法

或者,我应该只选择一种模式并专门使用它吗

提前感谢您提供的任何见解,
哈里森


PS.我从未实际开发过使用DDD的应用程序,因此,如果这是一个非常天真的问题,我很抱歉。

我想说,它们完全可以一起使用。事实上,我们在当前的项目中使用了这种组合,并取得了巨大的成功

命令处理程序是细粒度的,而DDD模型更具内聚性,这是正确的。但是,这些命令处理程序可以自由地以各种方式执行命令,可以是DDD或事务脚本。对于给定的命令/用例,您可以使用任何有意义的方法。因此,您不必为每个命令都使用DDD(有时您只需要一个简单的插入,而不需要涉及模型)


您的DDD模型可以在整个命令层共享。例如,您可能有5个customer命令,所有这些命令都在一个DDD customer模型对象上操作。

之所以是DDD,是因为您开始更多地考虑语言,您试图在代码中找到一个模型,该模型与您对域的理解“同步”。实际上的实现模式是实现细节。例如,我们可以尝试是否有更好的方法来表达命令,例如SetProjectAsActiveCommand->ActivateProject;AddCommentTopProjectCommand->CommentOnProject。我们放弃了开发人员语言(set、add、command),转而使用领域语言

在这种方法中,命令不做任何事情(它们不像GoF命令)。它们只是消息,代表用户的意图。聚合(和实体、值对象等)表示我们的结构域模型。他们知道如何做事、做决策、保护业务规则。。。在这些消息和决策之间,需要有接收消息并将其转换为域模型的东西。这些是命令处理程序:它们相当愚蠢,它们只是确保消息到达正确的聚合。因此,命令处理程序通常只会从存储库中获取聚合并告诉它做些什么,而不了解其内部结构。这将使命令与域模型巧妙地分离


你可能知道我是这种代码组织风格的忠实粉丝。我认为这对DDD非常有用。您可以通过许多其他方式应用DDD。最终,目标不是“进行DDD”,而是构建能够解决问题、可测试、可维护和可进化的系统

据我所见,经验丰富的开发人员倾向于这样做:DDD作为战略设计,基于消息的体系结构+CQR作为实现。