3

我有这样的 CQRS 命令

public sealed class RequestRoute
{
    public RequestRoute(string fromAddressName, double fromLatitude, double fromLongitude, string toAddressName, double toLatitude, double toLongitude, string userId)
    {
        UserId = userId;
        ToLongitude = toLongitude;
        ToLatitude = toLatitude;
        ToAddressName = toAddressName;
        FromLongitude = fromLongitude;
        FromLatitude = fromLatitude;
        FromAddressName = fromAddressName;
    }

    public string FromAddressName { get; private set; }
    public double FromLatitude { get; private set; }
    public double FromLongitude { get; private set; }

    public string ToAddressName { get; private set; }
    public double ToLatitude { get; private set; }
    public double ToLongitude { get; private set; }

    public string UserId { get; private set; }
}

我的程序员的直觉告诉我,我应该将 FromXXX 和 ToXXX 字段分解到一个名为“Address”的单独类中......但我不确定这是否违反了 CQRS 模式......我见过的所有例子都只使用原始类型作为命令和事件的属性。

4

6 回答 6

7

命令是面向数据的,而不是面向对象的。它的属性应该主要是基元。你没有在这里建模任何东西,只是发送平面数据。

使用自定义类型会强制您将类型发布到每个想要使用命令的客户端。它还将阻止您在将来轻松更改这些类型。

然后是可串行化:自定义类型越少越简单。

在命令和事件等消息中,我会尽可能合理地使用原语。重复不是这里的问题,你想要低耦合、可串行化、容错性。

于 2013-04-09T11:28:14.723 回答
4

就模式而言,在那里提取一个通用类型似乎很好。总体而言,命令一旦发出就不应更改,因此只需确保地址类型是不可变的(与原始类型一样)。

可能有一些实现约束需要考虑,即序列化。

于 2013-04-09T02:45:35.247 回答
3

在我看来,这样的重构没有真正的价值。

在可读性和维护期间写入route.ToLatituderoute.To.Latitude不改变任何内容。

但是,我会将double 字段更改为decimal(甚至是字符串)以避免在不同平台、机器或架构之间移动 DTO 序列化(无论是否为二进制)时出现任何问题。

于 2013-04-09T09:48:48.047 回答
1

您可以安全地将“To”和“From”重构为一个类。命令是您域的 API,所以只要您可以维护它 - 您应该很好。

PS 如果你问关于事件溯源中的事件的相同问题 - 答案会复杂得多

于 2013-05-01T15:03:21.477 回答
0

我认为这里有一点混乱。CQRS 只是意味着拥有单独的读取和“写入”(行为丰富)模型。RequestRoute 是命令,因此是消息而不是模型。CQRS 可以与消息驱动架构一起使用,但它不是必需的,因此这两者不相关。

在这种情况下,你是对的,FromXXX 和 ToXXX 应该是一个 Address 类,但这与 CQRS 无关,所以你没有违反任何东西。

顺便说一句,消息应该包含其处理程序所需的所有必需信息,以便您可以在其中放入很多东西,如果您知道消息将被持久化,唯一的问题是序列化,但消息只不过是 DTO反正。

于 2013-04-09T07:43:59.953 回答
0

在这里提取一个通用类型并没有错。在大多数情况下,您应该共享模式而不是类型,因此在这方面不会引起问题。

于 2013-04-15T12:27:08.540 回答