CQRS:命令返回值 [英] CQRS: Command Return Values

查看:27
本文介绍了CQRS:命令返回值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于命令是否应该有返回值似乎有无尽的困惑.我想知道混淆是否仅仅是因为参与者没有说明他们的背景或情况.

There seems to be endless confusion about whether commands should or should not have return values. I would like to know if the confusion is simply because the participants have not stated their context or circumstances.

以下是混淆的例子...

Here are examples of the confusion...

  • Udi Dahan 说命令不会向客户端返回错误",但是在同一篇文章中他展示了一个图表,其中命令确实将错误返回给客户.

  • Udi Dahan says commands are "not returning errors to the client," but in the same article he shows a diagram where commands indeed return errors to the client.

Microsoft Press Store 的一篇文章指出该命令...不返回响应";但随后给出了一个模棱两可的警告:

A Microsoft Press Store article states "the command...doesn't return a response" but then goes on to give an ambiguous caution:

随着围绕 CQRS 的战场经验的增长,一些实践会巩固并趋于成为最佳实践.部分与我们刚才所说的相反......今天的普遍观点认为命令处理程序和应用程序都需要知道事务操作是如何进行的.结果必须知道...

As battlefield experience grows around CQRS, some practices consolidate and tend to become best practices. Partly contrary to what we just stated... it is a common view today to think that both the command handler and the application need to know how the transactional operation went. Results must be known...

  • 吉米博加德说命令总是有结果";但随后会额外努力展示命令如何返回 void.
    • Jimmy Bogard says "commands always have a result" but then makes extra effort to show how commands return void.
    • 嗯,命令处理程序是否返回值?

      Well, do command handlers return values or not?

      借鉴 Jimmy Bogard 的CQRS 神话,"我认为这个问题的答案取决于什么程序化/上下文象限".你说的是:

      Taking a cue from Jimmy Bogard's "CQRS Myths," I think the answer(s) to this question depends on what programmatic/contextual "quadrant" you are speaking of:

      +-------------+-------------------------+-----------------+
      |             | Real-time, Synchronous  |  Queued, Async  |
      +-------------+-------------------------+-----------------+
      | Acceptance  | Exception/return-value* | <see below>     |
      | Fulfillment | return-value            | n/a             |
      +-------------+-------------------------+-----------------+
      

      验收(例如验证)

      命令接受"主要是指验证.据推测,验证结果必须同步提供给调用者,无论命令履行"是否有效.是同步的或排队的.

      Acceptance (e.g. validation)

      Command "Acceptance" mostly refers to validation. Presumably validation results must be given synchronously to the caller, whether or not the command "fulfillment" is synchronous or queued.

      然而,似乎许多从业者不会从命令处理程序内部启动验证.从我所见,要么是因为 (1) 他们已经找到了一种在应用层处理验证的绝妙方法(即 ASP.NET MVC 控制器通过数据注释检查有效状态)或​​ (2) 架构假设命令已提交到(进程外)总线或队列.后面这些异步形式通常不提供同步验证语义或接口.

      However, it seems many practitioners don't initiate validation from within the command handler. From what I've seen, it is either because (1) they've already found a fantastic way to handle validation at the application layer (i.e. an ASP.NET MVC controller checking valid state via data annotations) or (2) an architecture is in place which assumes commands are submitted to an (out of process) bus or queue. These latter forms of asynchrony generally don't offer synchronous validation semantics or interfaces.

      简而言之,许多设计人员可能希望命令处理程序将验证结果作为(同步)返回值提供,但他们必须忍受他们使用的异步工具的限制.

      In short, many designers might want the command handler to provide validation results as a (synchronous) return value, but they must live with the restrictions of they asynchrony tools they are using.

      关于履行";对于命令,发出命令的客户端可能需要知道新创建的记录的 scope_identity 或可能的失败信息 - 例如帐户透支".

      Regarding "fulfillment" of a command, the client who issued the command might need to know the scope_identity for a newly created record or perhaps failure information - such as "account overdrawn."

      在实时设置中,返回值似乎最有意义;异常不应用于传达与业务相关的失败结果.然而,在排队"中上下文...返回值自然没有意义.

      In a real-time setting it seems that a return value makes the most sense; exceptions should not be used to communicate business-related failure outcomes. However, in a "queuing" context...return values naturally make no sense.

      这就是所有困惑的总结:

      This is where all the confusion can perhaps be summarized:

      许多(大多数?)CQRS 从业者认为他们现在或将来会合并一个异步框架或平台(总线或队列),因此宣称命令处理程序没有返回值.然而,一些从业者无意使用这种事件驱动的结构,因此他们会认可(同步)返回值的命令处理程序.

      Many (most?) CQRS practitioners assume they will now, or in the future, incorporate an asynchrony framework or platform (a bus or queue) and thus proclaim that command handlers do not have return values. However, some practitioners have no intention of using such event-driven constructs, and so they will endorse command handlers that (synchronously) return values.

      因此,例如,当 Jimmy Bogard 提供了这个示例命令界面:

      public interface ICommand<out TResult> { }
      
      public interface ICommandHandler<in TCommand, out TResult>
          where TCommand : ICommand<TResult>
      {
          TResult Handle(TCommand command);
      }
      

      他的 Mediatr 产品毕竟是一种内存工具.鉴于这一切,我认为原因 Jimmy 小心地花时间从命令中产生一个无效的返回并不是因为命令处理程序不应该有返回值",而是因为他只是希望他的 Mediator 类具有一致的接口:

      His Mediatr product is, after all, an in-memory tool. Given all this, I think the reason Jimmy carefully took the time to produce a void return from a command was not because "command handlers should not have return values," but instead because he simply wanted his Mediator class to have a consistent interface:

      public interface IMediator
      {
          TResponse Request<TResponse>(IQuery<TResponse> query);
          TResult Send<TResult>(ICommand<TResult> query);  //This is the signature in question.
      }
      

      ...即使并非所有命令都有有意义的返回值.

      ...even though not all commands have a meaningful value to return.

      我是否正确地理解了为什么在这个主题上存在混淆?有什么我遗漏的吗?

      Am I correctly capturing why there is confusion on this topic? Is there something I'm missing?

      在给出的答案的帮助下,我想我已经解开了困惑.简而言之,如果 CQRS 命令能够返回指示完成状态的成功/失败,则返回值是有意义的.这包括返回新的 DB 行标识,或任何未读取或返回域模型(业务)内容的结果.

      With the help of the answers given, I think I've untangled the confusion. Put simply, if a CQRS command is capable of returning a success/failure indicating completion status, then a return value makes sense. This includes returning a new DB row identity, or any result that does not read or return domain model (business) content.

      我认为CQRS 命令"在哪里?出现混乱,是关于异步"的定义和作用.基于任务"和基于任务"之间存在很大差异.异步 IO 和异步架构(例如基于队列的中间件).在前者中,异步任务"是可以并将提供异步命令的完成结果.但是,发送到 RabbitMQ 的命令不会类似地收到请求/响应完成通知.正是异步架构的后一种上下文导致一些人说没有异步命令这样的东西".或命令不返回值."

      I think where "CQRS command" confusion emerges, is over the definition and role of "asynchrony". There is a big difference between "task based" async IO, and an asynchronous architecture (e.g. queue based middle-ware). In the former, the async "task" can and will provide the completion result for the async command. However, a command sent to RabbitMQ will not similarly receive a request/reponse completion notification. It is this latter context of async-architecture that causes some to say "there is no such thing as an async command" or "commands do not return values."

      推荐答案

      遵循 解决 CQRS 中的复杂性 作者 Vladik Khononov 建议命令处理可以返回与其结果相关的信息.

      Following the advice in Tackling Complexity in CQRS by Vladik Khononov suggests command handling can return information relating to its outcome.

      在不违反任何 [CQRS] 原则的情况下,命令可以安全地返回以下数据:

      Without violating any [CQRS] principles, a command can safely return the following data:

      • 执行结果:成功或失败;
      • 错误消息或验证错误,以防万一;
      • 聚合的新版本号,如果成功;

      此信息将显着改善您系统的用户体验,因为:

      This information will dramatically improve the user experience of your system, because:

      • 您不必为命令执行结果轮询外部源,您可以立即获得.验证命令和返回错误消息变得微不足道.
      • 如果你想刷新显示的数据,你可以使用聚合的新版本来确定视图模型是否反映了执行的命令.不再显示陈旧数据.

      Daniel Whittaker 提倡返回常见结果"来自包含此信息的命令处理程序的对象.

      Daniel Whittaker advocates returning a "common result" object from a command handler containing this information.

      这篇关于CQRS:命令返回值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆