Domain driven design 命令的命名约定&;事件

Domain driven design 命令的命名约定&;事件,domain-driven-design,cqrs,dddd,Domain Driven Design,Cqrs,Dddd,我刚刚进入事件驱动架构,想知道命名命令和事件的约定是什么。我知道这么多:命令应该以DoSomething的形式出现,而事件应该以something的形式出现。我需要澄清的是,如果我需要在我的命令后面加上“命令”一词,在我的事件后面加上“事件”,例如DoSomethingCommand,而不是DoSomething和something happenedevent,而不是something happenedevent。我还想知道社区首选公约背后的理由是什么。谢谢 我的约定取决于名称空间,我的意思是我

我刚刚进入事件驱动架构,想知道命名命令和事件的约定是什么。我知道这么多:命令应该以DoSomething的形式出现,而事件应该以something的形式出现。我需要澄清的是,如果我需要在我的命令后面加上“命令”一词,在我的事件后面加上“事件”,例如DoSomethingCommand,而不是DoSomething和something happenedevent,而不是something happenedevent。我还想知道社区首选公约背后的理由是什么。谢谢

我的约定取决于名称空间,我的意思是我从不使用后缀事件或命令

我还根据命令和事件要影响的聚合类型将它们组织到单独的名称空间中

例如:

// Commands
MyApp.Messages.Commands.Customers.Create
MyApp.Messages.Commands.Orders.Create
MyApp.Messages.Commands.Orders.AddProduct

// Events
MyApp.Messages.Events.Customers.Created
MyApp.Messages.Events.Orders.Created
MyApp.Messages.Events.Orders.ProductAdded

根据您的需求,您可能希望将事件放置到单独的程序集中。这样做的原因可能是您需要将事件分发到下游系统。在这种情况下,您可能不希望下游系统不得不为您的命令操心(因为它们不应该操心)。

命令和
事件
后缀是可选的,是首选项。我宁愿省略它们,并试图仅从名称中看出意图。命名命令和事件最重要的方面是确保它们更能反映业务领域而不是技术领域。很多时候,像Create、Update、Add和Change这样的术语太过技术化,在业务领域的意义也不大。例如,与其说是
UpdateCustomerAddress
,不如说是
RelocateCustomer
,因为它可能有更大的业务上下文。

如果您的命令/事件的名称正确,添加命令和事件将是多余的信息。这将是使代码可读性降低的噪声。还记得匈牙利符号吗?大多数程序员(据我所知)不再使用它了。

命令和事件为您的应用程序形成了一种语言……一种API。使用诸如“命令”和“事件”之类的术语可能对系统级定义很有用,因为在系统级定义中,技术术语被有意义地混合到实体的用途中,但是如果您处理的是域行为的定义,那么就不要使用系统/技术术语,而使用业务术语。这将使你的代码读起来更自然,减少打字。 我从“Command”/“Event”附件开始,但意识到这是浪费时间,并使我远离了普遍流行的DDD语言。 嗯,,
Mike

我经常看到并使用的惯例是,事件应该是过去式,并描述发生了什么:

  • 用户注册
  • 帐户激活
  • 答复
命令是您希望执行的操作。因此,创建名称来说明:

  • CreateUser
  • UpgradeUserAccount
至于组织,我通常将它们与它们所用于的根聚合放在一起。这使得查看您可以做什么以及生成什么类型的事件变得更加容易

也就是说,我为每个根聚合创建了一个名称空间,并将所有内容(存储库定义、事件、命令)放在它下面

  • MyApp.Core.Users
  • MyApp.Core.Posts

等等。

非常感谢,@mikael。这很有道理,也是我目前所倾向的方向。我只是想澄清什么是标准实践。我不会说这是标准实践。我就是这样做的。然而,我认为这遵循了.Net的惯例,即使用名称空间作为全名的一部分,而不是用后缀之类的东西重复自己。唯一的缺点是,当您想要为名为
Created
的20多岁事件中的一个添加using语句时,resharper提供了大量选项。我倾向于将命令和事件分离到单独的程序集中,并使用不同的名称空间,如上文所述的@MikaelÖstberg。我也不主张在这些消息的末尾添加命令或事件+1@MikaelÖstberg如果创建客户的命令失败,即负载缺少值,您是否仍会发送创建的事件?如果不是,你会发送什么事件?我不会创建客户。我会抛出一个异常,并让命令在错误队列中结束。谢谢!就这么做了。花了一点时间才弄明白如何实现。谢谢,我已经开始使用这种方法实现。我也喜欢@MikaelÖstberg关于使用名称空间的观点。不过,我注意到的一个小问题是,在实例化对象时,附加事件/命令的阅读效果似乎更好。比较:
var userSignedOut=newusersignedout(){}
总线发布(userSignedOut)带有
var userSignedOutEvent=new userSignedOutEvent(){}总线发布(userSignedOutEvent)