2017-06-27 90 views
2

我目前使用Scala和Eventuate,但我認爲這個問題適用於任何情況下采購環境:如何處理事件源應用程序中的域更改?

比方說,你有以下事件:case class UserAdded(user: User),並Usercase class User(username:String, birthday: Date)

您的應用已運行一段時間,現在您需要收集用戶的電話號碼。所以現在我們需要將User更改爲case class User(username:String, birthday: Date, phoneNumber: String)

當事件重播時,它會拋出錯誤,因爲過去的事件沒有phoneNumber。你通常如何在事件源應用程序中解決這個問題?

我的第一個想法是爲事件存儲中的所有事件設置一個默認值,但是我明白事件源是不可變的,所以我決定聽取更多有經驗的用戶的意見。

任何輸入是非常感謝!

回答

2

你所描述被稱爲「版本」事件採購和,儘管事件採購是一個相對較新的技術,至少有兩種解決方案:

  1. 你保留舊事件(班級和數據),併爲未來活動引入新的活動類型,如class UserAddedV2(username:String, birthday: Date, phoneNumber: String)。這有一個缺點,即舊類將繼續存在,儘管它不再被實例化。

  2. 您可以遷移整個事件流,並用新的事件替換舊事件,並使用新字段的默認值。這樣你就可以擺脫舊的事件類。

我強烈推薦Greg Young的book,因爲這是我在這個主題上找到的最好的。

+0

我認爲承認重寫事件流的可能性是一個滑動斜率:在你知道它之前,其他所有部署都需要重寫歷史記錄。 –

+0

@FyodorSoikin Events以強大的方式將數據綁定到代碼,只有歷史重寫可以打破這種耦合,恕我直言。無論如何,至少應該知道這個戰術模式 –

+0

真棒書!我不知道。它涵蓋了深入的問題,謝謝! –

5

我認爲這裏有兩個概念錯誤。

首先,一個事件不應該「引用」或「包含」一個域對象。事件是發生事件的記錄,因此它應明確記錄表徵它的數據點。在這種情況下 - usernamebirthday

case class UserAdded(username:String, birthday: Date) 

現在,這一事件定義可以永遠不會改變。發生了什麼,發生了。沒有重寫過去。

如果在某一點上,業務需求的變化,這意味着從現在開始不同類型的事件會發生:

case class UserAdded2(username:String, birthday: Date, phoneNumber: String) 

這兩個事件都應該保持不變,則雙方應進行處理,加工, 隨你。正如直覺所暗示的那樣,第一個事件並非「現在無用」。恰恰相反:第一個事件記錄了需求改變之前發生的事情,並且該記錄是有價值的。

現在,根據您的平臺允許的情況(我不熟悉Eventuate),您可以在技術上將這兩個事件作爲具有可選字段的單個類來實現。但即使你這樣做,你也應該永遠記住,這個班級代表了兩個不同的事件。出於這個原因,我寧願將它們明確定義爲單獨的東西。

相關問題