2012-02-06 112 views
5

我對DDD(域驅動設計)在過去幾天感興趣,但我無法弄清誰創建和驗證實體的責任。我會打破這個問題以涵蓋不同的場景。DDD - 實體創建和驗證責任

  1. 正則實體(可能帶有值對象)。舉一個例子,讓我們接受一個由電子郵件標識的用戶。我有一個UserFactory接收一組數據(可能來自POST表單),並返回一個新的UserEntity。工廠是否應該驗證數據的完整性(例如:Email給的字符串是真實的電子郵件,密碼字段1和字段2的密碼等)?工廠應該驗證沒有這樣的用戶存在(我們不想使用同一封電子郵件註冊兩個用戶)?如果是的話,它應該做我自己還是使用UserRepository?

  2. 集合實體。讓我們假設我們有一個Post實體和評論實體。我想獲得所有評論12後,所以我做類似

    $ post = $ postRepository-> getById(12);

getById應該如何實現?像這樣:

public function getById($id) { 
    $postData = $this->magicFetchFromDB($id); 
    $comments = (new CommentRepository())->getForPost(12); 
    return new PostEntity($postData, $comments); 
} 

或者這個職位負責懶人創造的意見,是這樣的:

class PostEntity { 
    public function getComments() { 
     if(is_null($this->_comments)) $this->_comments = (new CommentRepository())->getForPost($this->_id); 
     return $this->_comments; 
    } 
} 

? 我在這裏很迷茫,沒有足夠的信息與PHP中的DDD的例子,所以任何幫助將不勝感激!

非常感謝, skwee。

回答

4
  • 工廠應該只有關心創建實體。我個人更喜歡在我的視圖和模型層中進行驗證。我會使用jQuery的驗證插件之類的庫來在客戶端進行一些必需的驗證(例如,檢查所需字段是否有數據)。然後對模型進行「核心」驗證。 我做,這是通過簡單的BaseEntity抽象類,所有的實體延伸,既然你問了一個例子,那就是:

    abstract class BaseEntity { 
        public function isValid(); 
    }   
    
    class MyEntity extends BaseEntity { 
        public function isValid() { 
         //actual validation goes here 
        } 
    } 
    

    你也可以使用一個靜態輔助類的一些基本驗證方法:

    class ValidationHelper { 
        public static function isValidPhonenumber($value) { 
         //check valid phonenumber, using a regex maybe 
        } 
    
        public static function isAlphanumeric($value) { 
         //check for letters and numbers only 
        } 
    } 
    

    很多反對的靜態方法,因爲它們可以打破單元測試,但在這種情況下,他們是非常基本的,他們沒有外部的依賴,從而使他們「更安全」。

  • 當涉及到檢查已經存在的實體時,您可以通過查詢您的數據庫來查看實體是否已經存在,然後再添加/更新,或者(我喜歡這樣做),您可以添加一個unique指向那些不能在數據庫中重複的列的索引,然後將創建或更新查詢包裝在try-catch塊中(例如,如果兩個用戶具有相同的電子郵件,則查詢將拋出唯一的約束違例)然後顯示正確的錯誤信息

  • 關於你的最後一個問題,它歸結爲一個偏好問題。如果您的數據庫將在1分鐘內獲得百萬次點擊,那麼最好使用延遲加載來避免在需要時提取不需要的數據。但是如果你的數據庫比較小,你可以完美地使用急切的加載而不犧牲太多的性能。 同樣,這是個人喜好的問題。

希望一些這種散漫有道理,歡呼!

+0

感謝您的評論! A)我不確定是否要在實體中進行驗證。你會考慮驗證captcha是否是業務邏輯的一部分?如果我有管理面板手動添加用戶而不需要驗證碼? B)是的我可以,但問題是這是誰的責任?驗證圖層?廠?庫? C)好吧,但是如果我的用戶有帖子發表評論,如果加載所有這些數據以顯示用戶個人資料頁面,這會很聰明嗎? – 2012-02-08 21:35:32

+1

a)它確實取決於您的需求,我發現使用助手類在實體本身進行驗證「更容易」。但增加一層額外的驗證非常好。 b)我會說這是驗證層的責任。如果兩個賬戶不能有相同的號碼,並且您嘗試添加一個已經存在的號碼,這意味着該實體** ** **,或者至少這就是我的想法。 – jere 2012-02-09 18:02:13

+1

c)這也取決於你想要什麼。如果您要在個人資料頁面上一次顯示所有信息,那麼請在一次調用中加載所有信息。但是如果你展示的是,只能發佈帖子,並且當你點擊一個顯示評論的時候,最好在那一刻加載評論,或許使用ajax – jere 2012-02-09 18:03:14

1

最好的和最簡單的方法是使用Doctrine2。也許第一個小時很難,但是一旦你掌握了Doctrine2,所有這些關係和聚合都是小菜一碟。

您可以在http://giorgiosironi.blogspot.com/或只是通過Google搜索找到關於PHP & DDD或Doctrine2的大量信息。

RE:驗證 - 考慮我們使用驗證對象的單一責任原則。驗證可能很複雜,可能需要其他儲存庫或實體,因此最好將其與實際實體保持分開 - 驗證的主題以避免創建浮腫對象。您可以使用訪客或規範設計模式。

這裏有很多關於這些主題的其他帖子 - 嘗試使用上述關鍵字。

+0

當時我使用了教條,並不是很喜歡它,它很大很重。然而,它是在學說2之前,我可能會再次給主義一個鏡頭。不過,我仍然對正確的做事方式感興趣,而不是尋找現成的解決方案。至於驗證,感謝您攜帶SRP!我完全忘了它,並不確定是否應該插入另一層驗證,現在我確定我需要:) – 2012-02-08 21:31:29

+0

Doctrine基於Active Record模式,Doctrine2正是您需要的,以便於實現DDD。正如我在另一篇類似的文章中所寫的那樣 - 自制解決方案通常最終會因爲維護惡夢和聚合根源變得非常手動。通常每個AR都是根據開發人員製作的不同方式完成的。在那裏,相信我,你不想這樣... – 2012-02-14 02:24:25

+0

我有「重新發明輪子」綜合徵。如果我被要求在時間緊迫的情況下在我的工作場所實施DDD,我可能會遵循Doctrine。由於我的問題是從我的個人項目中提出的,我沒有嚴格的死線,所以我更願意通過實​​施這些東西來儘可能多地學習。我有一個很好的ATM解決方案,但恐怕只要病人嘗試複雜化它就會中斷,所以我正在考慮教義。此外,AFAIK Doctrine不支持非數據庫存儲(即基於文件的數據庫或noSQL數據庫),這可能是未來的問題(我確定編寫驅動程序不是問題)。 – 2012-02-14 08:16:13