我想問一個我在遊戲實現中使用DDD的問題。如何在同一事務中創建ddd聚合並更新其引用的其他聚合?
我有一種情況,根據系統收到的消息,創建一個新的玩家聚合。問題來自於這個新聚合必須由另一個聚合(表聚合)使用其id來引用。這第二個聚合保留了一個值對象,其中包含關於表中玩家的信息,如他所選擇的位置或顏色。玩家聚合存儲玩家動作,因爲根據玩家數量和他們發佈的動作,表聚合可能變得很龐大,如果我把所有東西放在桌面上,數據庫中的鎖爭用代價太高。對於玩家能夠加入表格,必須首先傳遞一些驗證,例如未採用的顏色,已達到的最大玩家數量或玩家不活躍的遊戲,這就是爲什麼此值對象存儲在信息表格中的原因來自球員。
因此,基於此,我只在創建玩家聚合時發佈第一個要存儲在表外的動作。問題在於該表可能包含引用尚未創建的聚合的值對象,這會使代碼看起來很難看,因爲它會強制它檢查空引用。另一個選項,即首先創建玩家聚合,也會破壞設計,因爲創建玩家的驗證首先發生在桌子上。由於系統的併發特性,首先在表上進行驗證,然後創建玩家聚合,然後在從創建中接收事件時更新表,可能會導致很多競爭條件。我能想到的唯一事情就是在同一個事務中更新兩個聚合,但這違背了DDD規則。
有沒有什麼好的解決方案呢?我想最終這將與設計有關,但我想不出任何可以在不引入性能問題的情況下工作的方式。
謝謝。
怎麼樣像'player = table.newPlayer(...); playerRepository.save(播放器); tableRepository.save(table);'其中'Table'只是將VO添加到內部集合中。在這裏你不會修改同一個事務中的兩個聚合,因爲玩家只是被創建,沒有被修改。因此,玩家實例上不存在爭用。 – plalx 2015-03-02 14:58:47
你真的可以這樣做嗎?我認爲關於在同一交易中不修改兩個集合的全部內容也包括創建。即使這樣也不適用於我的情況,因爲玩家離開表格後不會從PlayerRepository中移除。我必須檢查,因爲我不知道我是否會破壞別的東西。還有一個要求是存儲玩家的快捷方式,但可能在另一個有界的上下文中,所以在他離開後移除玩家仍然可以安全。但我想知道,如果更新和創建在同一時間是有效的DDD。 – Kilian 2015-03-02 15:09:13
是的,我相信它是有效的,因爲沒有增加併發衝突的風險。例如。您只修改'Table'聚合或修改'Table'聚合,並且創建一個'Player'對象並保存它並不會改變任何併發衝突。併發衝突是避免在單個事務中修改**許多聚合的主要原因。 – plalx 2015-03-02 17:42:16