2011-08-25 50 views
6

我正在讀上一個SO類似的問題:How update an entity inside Aggregate,但我仍然不知道用戶界面應該如何與骨料內的實體交互。更新實體內的總

比方說,我有User,有一堆Address es。用戶是聚合根,而地址只存在於聚合內。

在網頁inteface,用戶可以編輯自己的地址。基本上,會發生什麼情況是:

  • 用戶看到它的Web界面
  • 他點擊某個地址,並且被重定向到這個頁面上的地址的列表:edit-address?user=1&address=2
  • 在這個頁面上,他得到一個他可以在這裏修改這個地址。

我,我們決定繞開總根,這將是直截了當:

  • 我們會直接與加載AddressId
  • 我們將更新它,然後將其保存

因爲我們想這樣做的DDD的方式,我們有不同的解決方案:

  1. 要麼我們要求用戶憑身份證得到這個地址:

    address = user.getAddress(id);
    address.setPostCode("12345");
    address.setCity("New York");
    em.persist(user);

    這種方法的問題是,海事組織,該聚合根仍對地址做了什麼沒有更多的控制權。它只是返回一個引用,所以與繞過聚合沒什麼區別。

  2. 或者我們告訴彙總更新現有的地址

    user.updateAddress(id, "12345", "New York");
    em.persist(user);

    現在的總擁有什麼這個地址來實現,並可以採取進入任何必要的行動控制更新地址。

  3. 或者我們把地址爲值對象,我們不更新我們的Address,而是刪除它,然後重新創建

    user.removeAddress(id);
    address = new Address();
    address.setPostCode("12345");
    address.setCity("New York");
    user.addAddress(address);
    em.persist(user);

    這最後的解決方案看起來優雅,但同時也意味着一個地址不能是一個實體。然後,如果有什麼需要被被視爲一個實體,例如因爲聚集中的另一個業務對象有它的參考?

我敢肯定,我失去了一些東西在這裏要正確理解總的概念,它是如何在現實生活中的例子使用,所以請不要猶豫,提出您的建議!

回答

4

不,你不會錯過任何東西 - 在大多數情況下,最好的辦法是2號(雖然我會調用該方法changeAddress然後updateAdress - 更新顯得那麼不-DDD),這就是不管一個地址是一個實體或價值對象。隨着通用語言你寧願說,用戶改變了他的地址,所以這正是你應該如何模擬它 - 這是changeAddress方法獲得,以決定是否更新屬性(如果地址是一個實體)或分配完全新的對象(當它是VO)。

下面的示例代碼假定最常見的場景 - 地址爲VO:

public void ChangeAddress(AddressParams addressParams) 
    { 
     // here we might include some validation 

     address = new Address(addressParams); 

     // here we might include additional actions related with changing address 
     // for example marking user as required to confirm address before 
     // next billing 
    } 

這是什麼樣的重要的是,一旦被創建的地址,它被認爲是有效的 - 不可能有任何無效的地址對象在你的聚合。不過,請記住,你是否應該遵循這個樣本取決於你的實際領域 - 沒有一條路可以遵循。儘管這是最常見的一個。這樣做的原因被賦予了許多答案的SO(例如,在此Basic Aggregate Question) -

是的,你應該總是通過聚合根遍歷執行您的實體操作。

無論事情是一個實體或VO取決於需求和您的域名。大多數情況下,地址只是一個值對象,因爲兩個地址之間沒有區別,即相同的值,並且地址在其生命週期中不會改變。但是,大多數情況下,這取決於你正在建模的領域。

另一個例子 - 對於大多數域的Money將是一個價值目標 - $ 10 $ 10,它除了量沒有標識。然而,如果你要模擬一個在票據水平上處理資金的域,那麼每個賬單都將擁有自己的身份(用某種唯一編號表示),因此它將是一個實體。

+0

感謝。這確實有道理,儘管我不確定如何實現'changeAddress()'方法。上面的例子是過分簡單化的,地址可能由十幾個字段組成,包括街道名稱,建築物編號,地圖上確切位置的LatLng點等。那麼你建議什麼,將所有這些參數放在方法參數中,或者從表單中創建某種瞬態對象(它也可以是Address對象),並將其作爲參數傳遞給此方法? – Benjamin

+0

我已經爲最常見的場景添加了示例代碼。我不擔心領域的數量--DDD實際上不是關於數據,而是關於關係和管理複雜性。 – kstaruch