2015-06-30 41 views
3

在我看到的大多数例子中,命令和事件都表示为类。这意味着你必须编写一个带有name属性的CorrectNameCommand类和一个带有name属性的NameCorrectedEvent类。鉴于命令和事件在大多数情况下都是序列化和反序列化的,并发送给其他方(编译时安全类型),这个显式类相对于更通用的类有什么优势?CQRS Commands and Events as generic classes?

实施例:

用名称(即表示命令的类型)

A命令类时,AG的应处理的命令和对象或名称/值对的任何阵列的关键其他参数。

一个Event类本质上是相同的(也许我们可以把共享部分放在一个CommandEventBase类中)。

命令(和事件)处理程序现在要检查命令(事件)的名称而不是它的类类型,并且必须依赖列表中参数的正确性(就像解串器必须依赖序列化格式正确)。

这是一个很好的方法吗?如果是的话,为什么它不被用在样本和教程中?如果不是,有什么问题?

+1

我会说这是关于可读性和明确。您会看到Command需要什么,并且您可以看到Event提供的内容。重要价值对在这里不是很有帮助。同样使用命名约定,很容易使用Ioc-Container来创建正确的Command和EventHandler。 – Jehof

+0

所以这是一个折衷?我还编写了一个通用命令处理程序,该处理程序可以自动调度到ag上具有匹配名称和匹配参数的方法。这甚至消除了为每个命令编写命令处理程序的工作(但不禁止它)。 –

+0

这不是说你有一个有很多方法处理你的命令的大类吗?而不是一个类处理每个命令? –

回答

6

复制

这是一个公平的一点是,当命令和事件序列化,编译时安全性丢失,但在一个静态类型语言,我还是更喜欢强类型的命令和事件类型。

原因是它给了你一个负责解释消息元素的代码库。序列化往往是相当(类型)安全的;反序列化是您可能遇到问题的地方。

不过,我宁愿在一个地方处理任何这样的问题,而不是分散在整个代码库中。

这对事件特别重要,因为您可能有多个事件处理程序处理相同类型的事件。如果您将事件视为弱类型的字典,则需要在每个事件处理程序中执行 重复。另一方面,如果您将事件和命令视为强类型,则您的反序列化器可以是您必须维护的单个容错读取器。

类型

这一切说,我能理解你为什么,如C#或Java语言,发现,定义为每一位消息不可改变的DTO似乎是一个很大的开销:

public sealed class CorrectNameCommand 
{ 
    private readonly string userId; 
    private readonly string newName; 

    public CorrectNameCommand(string userId, string newName) 
    { 
     this.userId = userId; 
     this.newName = newName; 
    } 

    public string UserId 
    { 
     get { return this.userId; } 
    } 

    public string NewName 
    { 
     get { return this.newName; } 
    } 

    public override bool Equals(object obj) 
    { 
     var other = obj as UserName; 
     if (other == null) 
      return base.Equals(obj); 

     return object.Equals(this.userId, other.userId) 
      && object.Equals(this.newName, other.newName); 
    } 

    public override int GetHashCode() 
    { 
     return this.userId.GetHashCode()^this.newName.GetHashCode(); 
    } 
} 

那的确,好像很多工作

这就是我最近更喜欢其他语言来实现CQRS的原因。上 。NET,F#是一个完美的结合,因为所有上面的代码归结为一个班轮

type CorrectNameCommand = { UserId : string; NewName : string } 

这就是我想要做的,而不是通过弱类型周围字典。上次我听说格雷格扬谈论CQRS(NDC奥斯陆2015)时,他似乎也“转换”为F#。

+0

转换为F#对我来说不是短时间选项。 :-)因此,也许最好的方式是使用像你在F#中编写的DSL一样的东西,并生成C#。 –

+2

您是否考虑过在F#中定义类型,并将它们打包到库中?从C#开始,这些记录将看起来像不可变的类(基本上与我的C#示例中的CorrectNameCommand类没有区别;这就是它们编译的内容)。 –

+0

好主意。我会试一试。谢谢。 –