2012-03-22 63 views
5

一個實體(比方說一個UserEntity)對它的屬性有嚴格的規則,它可以存在兩種狀態 - 持久化(意味着它有一個id)和預先持久化(這意味着它還沒有id)。如何在持久化之前處理域實體驗證?

根據對this question about how to handle required properties的回答,「真正的」用戶實體只能通過傳遞給其構造函數的id創建。

但是,當我需要從瀏覽器發送的信息創建一個new UserEntity時,我需要能夠在持久化到db之前驗證信息。

在過去,我會簡單地創建一個空白UserEntity(無id),設置新的屬性,以及驗證它 - 但是,在考慮實體的這種新的,更安全的方法,我不應該永遠創建一個不帶id的新UserEntity。

我不想創建兩個知道如何驗證我的UserEntity屬性的地方,因爲如果他們改變了(他們會改變的話),它將會更新代碼兩倍並且增加錯誤的機率。

如何有效地集中我實體屬性的驗證知識?

注意

我有一個想法體現in this question,其中我認爲存儲在標準值對象,它會知道有關它的性質的規則,如電子郵件,密碼和名字的非國有性質不同的服務,如Controller,Validator和Repo或Mapper可以使用。

回答

4

這就是工廠的用途。在工廠方法中,您僅傳遞實施UserEntity的實際不變量所需的數據(需要一些時間來弄清楚您的UserEntity的不變量是什麼,並且您最好使用您的領域專家來做)。

在工廠方法

您創建一個新的ID,並把它傳遞給UserEntity構造。

在這個階段,我不認爲如果構造函數內部的驗證失敗,那麼拋棄實例就不好。在最糟糕的情況下 - 你失去了一個ID ...假設經常發生的情況並非如此 - 大多數情況下數據應該在客戶端進行驗證。

當然,另一種選擇是,在工廠方法首先驗證參數,然後才創建一個新的ID,並將其傳遞給UserEntity構造。

itzik saban

+0

任何人都可以用更簡單/不同的方式解釋這個嗎? – johnnietheblack 2012-03-22 21:39:31

0

在我看來,保存()和load()方法應該做的事情都驗證和設置ID屬性。順便說一下,沒有身份屬性的實體根本就不是一個實體。

在我看來,身份屬性應該進行驗證,並確保當實體是在運輸過程中如從數據庫

裝載,從文件或(後)保存加載到數據庫,從而

如果從數據庫加載失敗丟棄保存到數據庫/文件的實體不會丟棄該實體。

由於驗證是商業記錄/行爲等,併爲更好的模式將是

策略模式(http://en.wikipedia.org/wiki/Strategy_pattern)

+0

save()和load()方法應該存在於這個想法中......實體本身還是像映射器那樣的其他位置? – johnnietheblack 2012-03-22 22:02:58

+0

顯然在父實體是具體的。驗證是一種行爲,在我看來,它本身並不是強制性的。例如,當您啓動一輛汽車時,可以說它的光線持續亮起,如果不是它仍然是一輛汽車。 – sakhunzai 2012-03-22 22:12:04

1

我認爲你有一個夫婦的選擇可以考慮:

(1)考慮您的第一個評論:

的實體(比方說,一個UserEntity)有嚴格的規則爲它的 properti它可以存在於2個狀態 - 持久化(這意味着它 有一個id)和預先持續的(這意味着它還沒有一個id)。

在這裏,你已經提到驗證實際上取決於實體是否被持久化。換句話說,如果實體沒有被持久化,那麼它應該沒有ID是有效的。如果繼續使用該域名規範,我覺得確認應當採取相應的行動(如返回的isValid即使沒有如果對象沒有被持久化的ID)

(2)如果假設「有效」是指對象有一個ID,那麼你需要在創建時生成ID。取決於你的ID如何生成,這可能會變得棘手(例如保存到數據庫並返回創建的ID,或者以某種方式生成唯一標識符,或...)

使用這兩種方法之一,可能值得實現通用基類(es )爲您的實體(例如ID),以幫助最大限度地減少在不同州的重複驗證。希望這也能保護派生實體免受通用驗證。

0

如何正確進行驗證的主題有點灰色地帶。

通常將驗證轉換爲不變和上下文驗證。不變驗證屬於那些根據您的問題領域必須存在的事物,以使您的模型在其預期的角色中正常工作。上下文驗證屬於在給定使用情境中有效的狀態(例如,用於電子郵件的聯繫人需要電子郵件地址,但不需要電話號碼;用於目錄郵件的聯繫人需要郵寄地址,但不需要電子郵件等)。

如果您希望體系結構純粹,那麼從技術上講,輸入驗證(您的客戶在用戶界面中鍵入的內容)以及給定實體的狀態是兩個不同的問題。理想情況下,您的域名應該不知道其編寫的特定類型的應用程序,因此不應因提供適合直接或間接使用的錯誤消息而將錯誤消息顯示回給用戶。這帶來了一些問題,因爲它可能會導致重複或三重錯誤檢查(客戶端,服務端,域級),所以很多人選擇更實用的方法來處理大多數實體外部驗證(例如驗證實體創建之前的輸入模型)。

0

我沒有看到持久無效數據的問題。有效與否是企業關注的問題,有時取決於具體情況。數據庫不關心這些業務規則。

如果我必須在網上填寫一個大表格,最後一步需要輸入我的信用卡信息,並且我沒有準備好我的信用卡,那麼我將不得不丟棄所有信息,並且下一次再次輸入它(這不會發生,因爲我寧願去別的地方)。我希望該應用程序能夠存儲我已經提供的信息,稍後我可以使其功能有效。只要它無效,我就不能在網上訂購東西。