6

我一直在阅读 Greg Young 和 Udi Dahan 关于 Command Query Responsibilty Separation 的想法,我读到的很多内容都引起了我的共鸣。我的域(我们跟踪正在交付的车辆)具有包含一个或多个停靠点的路线的概念。我需要我的客户能够通过调用 Web 服务在我们的系统中进行设置,然后能够检索有关路线和车辆行驶情况的信息。

在过去,我会拥有与我的域类非常相似的“缩减”DTO 类,客户将创建一个带有 StopDto 数组的 RouteDto,并调用我们的 CreateRoute 网络方法,传入 RouteDto。当他们通过调用 GetRouteDetails 方法查询我们的系统时,我会返回完全相同的对象给他们。CQRS 吸引人的方面之一是 RouteDto 可能具有客户想要查询的各种属性,但在创建 Route 时没有业务设置。因此,我创建了一个单独的 CreateRouteRequest 类,该类在调用 CreateRoute“命令”时传入,以及一个作为查询结果返回的 Route DTO 类。

class Route{
    string Reference;
    List<Stop> Stops;
}

但我需要我的客户在创建路线时向我提供路线和停靠点详细信息。在我看来,我也可以...

给我的 CreateRouteRequest 类一个 Stops(s) 属性,它是一个“东西”数组,代表他们需要提供的关于每个停靠点的数据 - 但我怎么称呼这个类?这不是一个停止,因为这就是我在我的 Route DTO 中调用 DTO 的列表,但我不喜欢“CreateStopRequest”。我还想知道我是否陷入了一种 CRUD 思维模式,考虑主从信息,并要求客户也这样想。

class CreateRouteRequest{
    string Reference;
    ...
    List<CreateStopRequest> Stops;
}

或者

他们调用 CreateRoute,然后多次调用 AddStopToRoute 方法。这感觉有点“行为”,但我将失去将创建包括其停靠点的路线视为单个原子命令的能力。如果他们创建了一个 Route,然后尝试添加一个由于某些验证问题而失败的 Stop,他们将有一个部分正确的 Route。

我无法为我将在选项 1 中使用的“StopCreationData”对象列表想出一个好名字,这让我想知道我是否遗漏了一些东西。

4

3 回答 3

6

我意识到这是一个非常古老的帖子,但我最近一直在努力解决一些类似的模式,并且觉得有必要为这个线程做出贡献。我认为导致 OP 感到脱节的一件事是,他们将领域术语硬塞进他们自己的操作语言中,而不是让他们的设计与领域保持一致。

提示是使用“创建”作为动词。我发现,“创建”在开发人员的脑海中与“插入”相同(想想“CRUD”),当我们第一次开始尝试 DDD 时,我们经常使用那个动词,因为它看起来不那么技术性。不过,这里“创建”的路线已经存在。它们只是被记录在系统中。同样,路线上的停靠点已经存在,但也正在记录中。感知和措辞的简单改变,也许通过使用 RecordRouteCommand 和可选的 RecordStopOnRouteCommand 集合,可能会解决一些混乱。允许单独发送停止录制命令也将在构建中提供更大的灵活性并增强 API。

我也同意 Szymon 关于请求与命令的观点。这种措辞也导致了与 cqrs 方法相反的想法。如果说 DDD 教会了我一件事,那就是我们在项目中使用的词语不仅重要,而且至关重要。

于 2014-04-03T00:54:17.380 回答
5

我不认为你缺少任何东西。

class CreateRouteRequest{
    string Reference;
    ...
    List<CreateStopRequest> Stops;
}

对我来说看起来不错。在我看来,使用 AddStopToRoute 的替代方法不是一个好主意,因为它创建的界面过于“健谈”,无法有效地远程调用。

于 2010-06-24T08:41:32.633 回答
2

但是,您使用 CreateRoute* Request * 似乎表明您正在使用请求/响应模式。

如果您真的向服务器发送命令,则服务器不应返回响应对象/消息。您可以让您的服务公开一个 ExecuteCommand 方法,然后调用它,传递您的 CreateRouteCommand。

请求/响应不是正确的 CQRS 恕我直言。

于 2011-03-17T13:25:21.453 回答