2010-09-04 66 views
8

您可以使用CQRS(Command-Query Responsibility Segregation)架构模式来构建一个像StackOverflow这样的站点吗?我对CQRS和DDD(域驱动设计)相对陌生,并且正在探索该模式,并尝试对我熟悉的模式进行建模。尽管我可以看到CQRS对于像StackOverflow这样的站点的许多方面很有用,但有一些我不确定的地方是可能的(或者至少我不能立即弄清楚)。具体做法是:CQRS可以用于像StackOverflow这样的网站吗?

  • 问问题当我创建一个问题,我看到它马上 并可以进行编辑。在 CQRS中,我发出一个命令,如 'AskQuestion',并创建一个名为'QuestionAsked'的事件 。最终, 问题被推送到 非规范化数据存储。但是SO的 体验是直接的。 CQRS可以使用 吗?
  • 投票我的投票 立即反映。在CQRS中,我想这些命令/事件 最终会通过事件 总线到读取存储。但是,SO立即给我 。

我的担忧真的围绕着SO提供的即时反馈的概念。 CQRS能提供吗?如果是这样,这将如何完成?有没有很好的例子说明如何处理这个问题?

如果有帮助,我的环境是VS2010/C#/ SQL2008R2,但我可以接受SQLite等其他选项。我还在研究NCQRS和LOKAD的框架,以及Mark Nijhof的示例和计划下载Greg Young的样本。我没有发现CQRS样品。

谢谢!

回答

7

你实际上在谈论的是“最终一致性”,它经常与CQRS同时讨论,但你可以独立使用任何一种技术。

要做的最简单的事情就是立即更新UI所使用的模型,并使用它将问题显示给用户以供进一步操作。为了让其他用户可以看到更新,可以继续进行各种工作,而不会阻止UI。为了这个工作,你需要验证你的命令,这样在发送它之前几乎肯定会成功(如果命令在执行期间失败了,那么你需要处理这种情况,例如,将某种回调结合到UI模型中) 。

同样值得注意的是,通常这类事件的'事件结果'如此之快以至于无论如何,即使对其他用户来说,一切都会立即出现。

3

当您提出问题时,您可以在UI中“伪造”数据。它看起来像是立即更新到用户(您),但是其他用户会看到您的问题需要一段时间。你需要做同样的事情来处理投票。

如果您需要即时反馈,您可以考虑其他解决方案。但是,您可以通过一些技巧在CQRS解决方案中提供即时反馈。例如,如果您需要验证用户名是否是唯一的,则可以查询读取的数据库以确定用户名是否存在。如果没有,你可以使用它。但是,如果其他用户在此期间选择了相同的用户名,则在命令端会出现冲突。你需要在你的域模型中处理这个,例如,给用户一个生成的用户名并通过电子邮件发送给他。他可以稍后将其更改为其他内容。

+3

“假”和“诡计”并不是很令人放心......这看起来更像是一种破解,而非解决方法。 – 2010-09-09 15:16:23

+2

通过假我的意思是,你不必发送数据回数据库/服务器,然后再转到需要数据的屏幕。在数据通过系统(写入和读取)之前不会有问题,但您必须训练用户刷新屏幕或设置某种牵引机制。这可能会影响用户体验。而且,这不是一个聪明的黑客;-) – Fossmo 2010-09-16 20:52:54

+0

让人放心,假的正是你需要的!这是一个思想转变... – gkdm 2010-10-14 20:51:16

1

通过伪造或欺骗手段,您可能会将事件视为“未决事件”,这可能会在提交/发布阶段成功,但可能会失败。您在执行客户端时进行的验证越多,在首次提交提交之前,其成功的可能性就越大。因此,如果您打算依赖未完成的提交,请在验证和业务规则暴露方面规划较厚的客户端。

然后,用户可以通过在UI中将数据标记或标记为依赖于“等待提交”来允许用户继续使用数据(用于进一步修改)。这将是对象或属性的元属性。当然,添加和使用该元属性会增加复杂性,但取决于应用程序可能是必要的用例。

客户端命令队列/历史记录可能是帮助处理后续事件依赖最终失败的未决提交的情况的一种方法。换句话说,依赖于未完成提交的任何内容都可以成为可以汇总的历史记录的一部分,在对失败的未完成提交进行更正时保存,展开并重新应用于已更改并重新提交的待处理事件,并且一旦发出通知挂起事件成功提交,所有后续客户端历史记录将开始展开,提交队列中的下一个项目,将其标记为当前未决事件。

5

让我们看一下这两个问题...

提问的时候我创建了一个问题,我立刻看到它,并可以进行编辑。在CQRS中,我发出一个类似'AskQuestion'的命令,并创建一个名为'QuestionAsked'的事件。最终,问题被推送到非规范化的数据存储。但是,SO的经验是直接的。 CQRS可能吗?

这可以很容易地实现。每个用户都需要立即看到问题还是只需要问问问题的人?如果它看起来每个人都需要1-2秒才会有所作为?大多数情况下,在最终一致的系统中,发送请求的用户与其他用户之间存在差异。

投票我的投票立即反映出来。在CQRS中,我会想象这些命令/事件最终会通过事件总线移动到读取存储区。但是,SO立即给我提供了信息。

是否立即给它?我们来试试另一个例子,Facebook。当你点击喜欢的东西时,它会立即显示在你的喜欢中?像竖起大拇指的UI技巧会让你感觉像是这样。另一个例子,亚马逊。当您点击添加到购物车时,它会立即进入您的购物车?诸如“加入购物车”或“竖起大拇指”之类的视觉表示让用户感觉它已完成。

有很多这样的技巧可以使最终一致的系统感觉像一个完全一致的系统。作为一个便笺,很多人认为这些事情都是为了可扩展性(有时是这种情况)而完成的。更多的时候他们正在为可靠性而努力。如果XYZ停机,问题就会发生。你想要奇怪的随机本地故障,还是想冒广泛中断的风险?在这里看到的最好的例子之一是检查亚马逊的kindle购买,它的奇怪,他们可以处理您的信用卡在100毫秒,而其他人需要3-5秒:)如果他们的信用卡处理系统停机?

相关问题