CQRS - 命令是否应该尝试创建“复杂”的主从细节实体?

时间:2010-06-16 15:32:42

标签: domain-driven-design cqrs

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

在过去,我会“删除”与我的域类非常相似的DTO类,客户会创建一个带有StopDto数组的RouteDto,并调用我们的CreateRoute web方法,传递RouteDto。当他们通过调用GetRouteDetails方法查询我们的系统时,我会向它们返回完全相同的对象。 CQRS的一个吸引人的方面是RouteDto可能具有客户想要查询的所有属性,但在创建Route时没有业务设置。所以我创建了一个单独的CreateRouteRequest类,它在调用CreateRoute“命令”时传入,而一个Route DTO类作为查询结果返回。

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

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

为我的CreateRouteRequest类提供一个Stops(s)属性,该属性是一个“某事”数组,表示他们需要提供的关于每个停止的数据 - 但是我该怎么称呼这个类?这不是一个Stop,因为我在Route DTO中调用了DTO列表,但我不喜欢“CreateStopRequest”。我也想知道我是否陷入了一种CRUD心态,在这里思考主要细节信息并要求客户这样思考。

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

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

事实上,我无法为选项1中使用的“StopCreationData”对象列表提供一个好名字,这让我想知道是否有一些我缺少的东西。

3 个答案:

答案 0 :(得分:6)

我意识到这是一个非常古老的帖子,但我最近一直在努力解决一些类似的模式,并觉得需要为这个帖子做出贡献。我认为导致OP失去联系的一件事是,他们将域名术语用于自己的操作语言,而不是将其设计符合域名。

提示是使用&#34;创建&#34;作为动词。 &#34;创建,&#34;我发现,和#34;插入&#34;相同在开发人员的心目中(想想&#34; CRUD&#34;),当我们第一次开始尝试使用DDD时,我们常常使用该动词,因为它看起来不那么技术性。正在创建的路线&#34;但这里已经存在了。它们仅仅被记录在系统中。沿着相同的路线,路线上的站点已经存在,但也被记录下来。感知和措辞的简单改变,可能是通过使用RecordRouteCommand和RecordStopOnRouteCommand的可选附带集合,可能已经解决了一些混乱。允许单独发送停止记录命令将提供更多的构造灵活性并加强API。

我也同意Szymon关于请求与命令的关系。这种措辞也会导致思考与cqrs方法相反。如果DDD告诉我一件事,那就是我们在项目中使用的词语不仅重要,而且非常重要。

答案 1 :(得分:4)

我认为你没有遗漏任何东西。

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

对我来说很好看。在我看来,使用AddStopToRoute的替代方案并不是一个好主意,因为它创建了太“有条不紊”的界面,可以远程有效地调用。

答案 2 :(得分:2)

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

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

请求/响应不合适CQRS恕我直言。