老妖的博客
          現實的中沒有幾個人能夠真為對方去死,甚至山盟海誓很快就會在金錢面前變的微不足道,這才是生活。沒有永遠的愛,除了你的父母對你,當然也就沒有永遠的恨,更沒有永遠的痛,時間是最好的治療大師,它會很快撫平你心靈上累累的傷痕。很多年以后你想起來時,那些在你生命中洶涌來往的人群至多是個模糊的影子或者毫無意義的名字
          posts - 105,  comments - 171,  trackbacks - 0
          Domain Object Model and Hibernate detached object
          假定我現在正在設計一套圖書館自動化系統,我想設計為領域驅動模型(也就是非貧血模型),持久層的模型為hibernate O/R Mapping
          http://www.martinfowler.com/bliki/AnemicDomainModel.html
          讓我們來關注系統中的三個類文件:LibraryUser , Borrow and Item
          表關系如下:
          LibraryUser --(1:M)--> Borrow <--(1:1)--> Item [<--(M:1)-- Book]
          LibraryUser.java:
           1 public class LibraryUser implements java.io.Serializable {
           2 
           3     private Long id;
           4     private Long version;
           5     private String cardKey;
           6     private String unifiedKey;
           7     private Date admissionDate;
           8     private Date expiryDate;
           9     private Set borrows = new HashSet();
          10     private Set reservations = new HashSet();
          11     private Set libraryUserTypes = new HashSet();
          12         ..
          13 
          14     // get , set
          15 
          16 }
          17 Borrow.java:
          18 public class Borrow  implements java.io.Serializable {
          19 
          20     private Long id;
          21          private Long version;
          22          private Date borrowDate;
          23          private Date dueDate;
          24          private Date returnDate;
          25          private Date reportlostDate;
          26          private Short renewedNo;
          27          private LibraryUserType libraryUserType;
          28          private Item item;
          29          private LibraryUser libraryUser;
          30     ..
          31 
          32     // get,set
          33 
          34 }
          35 Item.java:
          36 public class Item  implements java.io.Serializable {
          37 
          38          private Long id;
          39          private Long version;
          40          private String barcode;
          41          private String shelfMark;
          42          private Date lastCheckin;
          43          private Set borrows = new HashSet();
          44          private Book book;
          45          private ItemDuration itemDuration;
          46          private ItemStatus itemStatus;
          47          private ItemType itemType;
          48          private Location location;
          49          ..
          50 
          51     // get,set
          52 
          53 }

          在三個類中現在僅有數據屬性,現在我想再加一些方法。因為是一個圖書管理系統,借書是一個常規動作,
          所以第一步我想在LibraryUser類中加入borrow方法。如果我想領域驅動來設計的話應該如何放置borrow方法呢?
          如果上述是正確的話,方法如下:
          方法一.
          LibraryUser.java,
           1 public class LibraryUser implements java.io.Serializable {
           2 
           3     ..
           4 
           5     public void borrow(Item item,LibraryUserType libraryUserType) {
           6 
           7         Borrow borrow = new Borrow();
           8         borrow.setLibraryUser(this);
           9         borrow.setLibraryUserType(libraryUserType);
          10         borrow.setItem(item);
          11         borrow.setBorrowDate(new Date());
          12         
          13         // The code here suppose to check the this libraryUser can borrow the item or not
          14         // l skip it for simple dicussion , let's assume that not checking is required. :)
          15          
          16 
          17         this.getBorrows().add(borrow);
          18     }
          19 
          20 }
          然后在我的controller中,我只是在borrow方法中傳入item,libraryUserType參數保存它
          controllerA
          1 libraryUser.borrow(item,libraryUserType);
          2 getLibrary().storeLibraryUser(libraryUser);
          這樣看起來較為常見,因為每一個libraryUser借書,所以borrow方法應當屬于libraryUser
          但是如果我們要級聯保存liberaryUser(libraryUser是獨立的)的話,會導致會導致多次更新借書,除非你
          在borrow.hbm.xml設置select-before-update="true",但是會導致一些性能損失。
          Of course , we can do it another way , feed libraryUser, item , libraryUserType into borrow , and save borrow ,
          當然我們可以將libraryUser, item , libraryUserType注入borrow中來達到同樣的效果
          方法二、
          1     Borrow borrow = new Borrow();
          2     borrow.setLibraryUser(libraryUser);
          3     borrow.setLibraryUserType(libraryUserType);
          4     borrow.setItem(item);
          5     borrow.setBorrowDate(new Date());
          6     
          7 
          8     getLibrary().storeBorrow(borrow);
          這個方法對于關系型數據庫來說是非常常見的一種方法,保存一個borrow對象,
          我們僅僅需要LIBRARY_USER_ID, ITEM_ID ,LIBRARY_USER_TYPE_ID , 當然還有DUE_DATE , ...等等
          他只執行一句query.
          insert into BORROWS (VERSION, BORROW_DATE, DUE_DATE, RETURN_DATE, REPORTLOST_DATE, RENEWED_NO, LIBRARY_USER_TYPE_ID, ITEM_ID, USER_IDvalues (?, ?, ?, ?, ?, ?, ?, ?, ?)

          Q1. 方法2是否是一個貧血的領域模型呢?
          Q2. 領域建摩的方法是什么,我是不是從一開始就錯了呢?

          ------------------reply----------------------
          It wasnt clear from that what the relationship is between a borrow and a book.
          從上述描述來看在borrow和book之間的關系不是很清晰。
          第一個想法---封裝
          First thought - encapsulation...
          protected的item中除了簡單的屬性之外有沒有基于collection之類的get/set方法呢?
          譬如,一個getBorrows()方法返回一個set類型,或者返回一個Collections.unmodifiableSet(borrows)
          這樣的話,在沒有你的允許之下調用代碼不能修改你的對象內部狀態.
          borrow方法的安置...
          看起來將borrow方法放于LibraryUser中并不是最佳的位置。
          你的領域內有一個書庫的概念嗎?很明顯你想知道一個User借什么書,但是我想你更想知道所有User在同時借閱books的數量。
          在這種前提下我建議你創建一個BookRepository或者其他你想要的名稱。這個BookRepository總是在記錄borrow和你想要得到的用戶信息.
          如果你讓repository來控制borrow,并不級聯User的borrows,那么你就可以避免上述討論的性能損失。
          一個user的borrows將會被你在內存中/inverse mapping(如果你使用hibernate的話)管理。

          你閱讀過<<Patterns of Enterprise Application Architecture>>或者<<Domain Driven Design>>嗎?你一定會喜歡的

          posted on 2005-11-03 10:50 老妖 閱讀(1029) 評論(1)  編輯  收藏

          FeedBack:
          # re: 關于spring forum 的domain object 的第二篇討論
          2005-11-03 14:31 | Programmer's Life
          Q1:以Martin Fowler對于貧血模型的定義來講,方法二確實是貧血模型,因為分離了數據和行為。
          Q2:領域建模我個人這么理解,領域建模是根據業務場景(用例或用戶故事)進行OOAD形成的業務模型體,這是系統的核心模型,基于此模型再結合架構來完成整個系統的設計,想想OOAD產生的業務模型體會是怎么樣的,那其實就是一個符合Martin Fowler所說的Rich Domain Model,不用為了概念而概念,其實Rich Domain Model一直存在,而且很早以前N多的系統本來就是Domain Model驅動的。

          不一定任何時候Rich Domain Model就是最好的,在小的系統中Transaction Script就是比它好用,不要什么都去追求一步登天,Rich Domain Model和Anemic Domain Model各有優缺點和適合的場合。  回復  更多評論
            

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           

          <2005年11月>
          303112345
          6789101112
          13141516171819
          20212223242526
          27282930123
          45678910

          常用鏈接

          隨筆分類(48)

          隨筆檔案(104)

          好友鏈接

          我的豆瓣

          積分與排名

          • 積分 - 221146
          • 排名 - 257

          最新評論

          閱讀排行榜

          主站蜘蛛池模板: 临夏县| 蒲城县| 兴业县| 珠海市| 开封市| 吉木萨尔县| 兴宁市| 上栗县| 津市市| 苏尼特左旗| 华安县| 克山县| 唐海县| 喀喇沁旗| 神木县| 永城市| 新晃| 大方县| 芦溪县| 镇巴县| 新蔡县| 阿图什市| 汤阴县| 闸北区| 恩平市| 金山区| 方城县| 姚安县| 吴忠市| 鸡西市| 南汇区| 莱西市| 甘孜县| 普格县| 腾冲县| 江永县| 平舆县| 宝丰县| 虞城县| 石家庄市| 若羌县|