6

我有一個關於在DDD中檢查唯一性的問題。我知道已經有一些關於這個在stackoverflow上的問題,但他們並沒有真正回答我的疑問在DDD中的唯一驗證

聚合根可能持有存儲庫的引用來檢查更新/插入到數據庫時的唯一性?或者這是由應用程序服務而不是域模型完成的任務?

比方說,我要檢查,當用戶註冊 有跡象表明,我能想到的幾種方法用戶模型的用戶名是否是唯一的:

  • 用戶參考模型UserRepository,做驗證的唯一性檢查()
  • 創建一個域服務,使用UserRepository進行唯一性檢查(這對我來說似乎有點奇怪,因爲我認爲域服務通常只用於跨多個域模型的邏輯)
  • 創建一個規範對象在域圖層中,參照Use rRepository封裝獨特的檢查規則,以及應用服務層使用此更新之前做檢查/插入

如果我使用依賴注入,我仍然不知道如何在方法1注UserRepository到用戶,或方法2中的域服務或方法3中的應用程序服務,因爲在任何情況下,對於用戶/域服務/規範對象,我需要手動實例化對象,所以我似乎在IoC中使用服務定位器的唯一選項得到實例。但是,服務定位是一個反模式,所以我想避免它

任何示例代碼將不勝感激

+2

我會說你應該在服務層實現這一點。更具體地說,爲特定類型的業務邏輯(你的命令)定義一個驗證器類,然後在包裝服務類的裝飾器中處理驗證。 – Steven

+0

這會幫助你嗎? http://stackoverflow.com/a/11958251/625332 – Dmitry

+0

@Steven所以我應該創建一個UserValidator來實現用戶在服務層的檢查?是否認爲業務規則(用戶名的唯一性)泄漏到域層之外? –

回答

4

我認爲檢查獨特陷入庫責任。知識庫知道所有的聚合,因爲它假設模擬域的收集,所以很自然地要求存儲庫的唯一性(例如,你希望從HashMap的例子)。

// repository 
interface Users { 
    // implementation executes SQL COUNT in case of relation DB 
    bool IsNameUnique(String name); 

    // implementation will call IsNameUnique and throw if it fails 
    void Add(User user); 
} 

它是在一個意義上的漏抽象因爲在多用戶環境中,該需要在數據存儲裝置側(UNIQUE SQL約束,例如,或鎖定)被強制執行。

IsNameUnique可能不應該從用戶聚合中調用,我會將此調用移入應用程序或域服務,具體取決於您的應用程序的其餘部分的結構。

查看Uniqueness validation in CQRS Architecture替代方法。

+0

所以你建議遵循上面的方法2,創建一個域服務來調用存儲庫來檢查唯一性? DDD中的常見方式是如何在域圖層中創建驗證服務?我是DDD的新手,所以不太確定 –

+0

是否從域或應用程序服務使用此存儲庫取決於您的使用情況,只要您不從聚合中使用此方法,則任何一個都可以。 – Dmitry

+0

謝謝,最後我決定採用這種方法:http:// lostechies。com/jimmybogard/2007/10/24/entity-validation-with-visitors-and-extension-methods/ –