我试图去学习和应用CQRS设计方法(模式和体系结构)到一个新的项目,但似乎缺少一个关键部分.
我的客户端应用程序执行查询并从读取模型中检索轻量级只读DTO列表.用户选择一个项目并单击按钮以启动某个操作.通过创建相应的命令对象并将其发送到写入模型(命令处理程序执行操作,更新数据存储等等)来执行操作.但是,在某些时候,我需要更新UI以反映对该行动产生的申请状态.
用户界面如何知道什么时候刷新原始列表?
附加信息
我注意到大多数讨论CQRS的文章/博客都在他们的例子中使用MVC客户端应用程序.我现在正在开发一个Silverlight客户端,并开始怀疑该模式在这种情况下是否起作用.
后续问题
在更多地考虑了Bartlomiej的回应和随后的讨论之后,我想知道CQRS中的错误处理.鉴于命令基本上是即发即弃的异步操作,我们如何向UI报告错误情况?
我看到'刷新UI'采取以下两种形式之一:
即使在MVC中使用Post-Redirect-Get模式,在知道操作结果之前,您也无法真正重定向.到目前为止,我见过的所有例子都没有解决这些现实问题.
对于WPF客户,我一直在努力解决类似的问题。任何数据的重新查询触发器取决于您更新的数据,命令通常分为以下几类:
该命令是真正的即发即弃方法,它通知状态更改的后端,但是此更改无需反映在UI中,或者该更改对UI而言并不重要。
该命令将更改单个查询的结果
该命令通常(至少在我的域内)以级联方式更改多个查询的结果,也就是说,更改单个“高级”数据的状态可能会影响许多“低级”缓存。
我的第一个触发条件是页面加载,因为几乎所有页面都必须假设自上次访问以来数据已被更新,所以很少有项目免于此。尽管某些系统可能只用这种方式更新财务和其他关键数据就可以逃脱。
对于简短的命令,当命令返回“成功”时,我也会更新数据。尽管由于IMHO这大部分都是懒惰,但所有CQRS命令都应异步触发。这仍然是我生活中不可或缺的一种选择,但是如果您的实现期望命令和查询之间的高延迟,则可能不得不这样做。
我开始使用的一种模式是介体(大多数MVVM框架都附带一种)。当我发出命令时,我还会向中介发送一条消息,指定启动了哪个命令。每个Cache(一个View模型属性Retriever<T>)都侦听影响它的命令,然后适当地进行更新。我尝试尽量减少消息的数量,同时又尽量减少从单个消息中不必要更新的高速缓存的数量,因此,我(希望)最终会获得简短的更新原因列表,每个“原因”都会更新高速缓存列表。
另一种方法是简单的诚实,我发现通过以图形方式公开系统如何更新自身,使用户更愿意耐心等待。触发命令时,显示一些UI,指示您正在等待成功的响应;出现错误时,您可以提供重试/显示错误的内容;成功时,您将开始相关字段的更新。请记住,此命令可能是从另一个终端(您不知道的终端)触发的,因此数据最终将需要超时以避免丢失其他计算机也调用的状态更改。
具有讽刺意味的是,更新客户端上的缓存和值的唯一有效方法是取消分隔命令并再次查询,无论是通过硬编码还是诸如哈希映射之类。