2017-06-22 66 views
1

我們正在考慮在工作中實施CQRS模式,並且有幾個關於驗證的問題。事件驗證

比方說,我們有3個總根源:

  • User
  • Business
  • UserToBusinessRelationship

當用戶註冊發送的事件是:

UserCreated 
BusinessCreated 
UserAddedToBusiness 

需要驗證事件,例如創建用戶和企業之間的鏈接應創建用戶和企業。

我看到兩種方法。

  1. 預先驗證:使用上次處理的快照加上未處理的事件即時構建讀取模型並將其用於驗證。

  2. 處理時驗證:接受事件/命令,並在處理事件時進行驗證。

第一種方法有即時反饋,但它需要創建一個最終讀取模型來驗證。其次更簡單,但不向消費者反饋出現問題。

我在想這樣的事情:當你發出一個事件時,你會找回一個你稍後可以用來查詢事件狀態的id。如果事件處理成功,你會得到'OK',否則你會得到一個錯誤,告訴出了錯誤。

這是一個有效的方法或矯枉過正?消費者如何知道事件已經被處理並且數據已準備好被使用?

+1

你是什麼意思的「事件驗證」?在CQRS中,只有命令被驗證;在他們被接受並且事件產生之後,這些事件必須被接受,它們被認爲是非常有效的,它們代表已經發生的事實。 –

+0

也許回答你的問題在這裏:http://danielwhittaker.me/2014/11/22/4-secrets-inter-aggregate-communication-event-sourced-system/ –

回答

3

偉大的問題Leonti - 你可能會發現我的博客帖子在CQRS系統驗證有用。你可以在這裏找到:How To Validate Commands in a CQRS Application

只需從標題注意到CQRS的重點是驗證命令而不是事件。

爲什麼?

因爲命令可以來自用戶輸入,因此不應該被信任。另一方面,事件是從域內發出的並且是可信的。 CQRS的實現可能涉及離開系統邊界的事件或接收非系統內事件的事件。在這些邊緣情況下,應該謹慎使用。

另一個潛在的紅旗是你描述你的聚合的方式。在我看來(並且我不知道你的域名是如何不能100%確定的),它們更類似於數據庫中的表格而不是聚合。重要的是不要讓你的持久性機制決定你的模型。

更具體地回到你的問題。

一般來說有兩種類型的驗證。膚淺而深沉。膚淺的東西就像丟失的字段,有效的電子郵件地址等等。深層次是域概念發揮的時候。例如貨物的重量是必需的和表面的驗證,但貨物是否適合承運人可能是一個領域的概念。

您可能需要驗證事物是否存在。企業或用戶是否存在?雖然這種驗證很可能會要求您訪問數據庫,但它仍然很膚淺,因爲它不太可能是明確的域名概念。

無論如何,我希望有所幫助。

2

這裏有兩個主要方面:

  1. 在CQRS你有命令和查詢。事件來自哪裏?假設您還指「事件採購」,但在使用命令時,您還需要在客戶端進行一些驗證,其中一些位於命令處理程序中,另一些位於您的域模型中(集合不變量和約束)。這個特定的例子看起來像是在客戶端和命令處理程序內部驗證的東西。

  2. 請記住,由於您對三個不同的聚合有三個不同的操作,所以您需要有三個事務。這意味着,如果其中一個無法完成 - 系統將進入無效狀態。您或者需要重新考慮聚合邊界以獲得一個聚合根,或者考慮使用其他技術,如事件驅動策略,傳奇(流程管理器)或路由單(sagas)。

當然,UserToBusinessRelationship聽起來更像是一個比一個聚合關係數據庫許多一對多連接表,但我不知道你的域東西。