我的評論
re: 領域驅動設計系列文章(2)——淺析VO、DTO、DO、PO的概念、區別和用處 Johnny.Liang 2010-08-06 00:05
@isnumeric
PO應該是我系列博文所說的DTO,它是實體的信息封裝對象,本質上與“實體的查詢信息封裝對象”是不同的,因此最好提供一個Criteria來封裝查詢屬性。
HQL絕對不能封裝在Service中,因為HQL涉及數據訪問邏輯,應該封裝在數據訪問層中,業務層可以傳入生成HQL的相關數據,由DAO把這些數據轉換為HQL,但Service絕對不要傳入任何與數據訪問實現細節有關的數據,否則Service就被耦合了。
PO應該是我系列博文所說的DTO,它是實體的信息封裝對象,本質上與“實體的查詢信息封裝對象”是不同的,因此最好提供一個Criteria來封裝查詢屬性。
HQL絕對不能封裝在Service中,因為HQL涉及數據訪問邏輯,應該封裝在數據訪問層中,業務層可以傳入生成HQL的相關數據,由DAO把這些數據轉換為HQL,但Service絕對不要傳入任何與數據訪問實現細節有關的數據,否則Service就被耦合了。
re: 領域驅動設計系列文章(2)——淺析VO、DTO、DO、PO的概念、區別和用處 Johnny.Liang 2010-07-01 17:38
@DDD
對,但頁面查詢用的VO,與表示某個實體的VO不是同一樣東西,如果按我的博文中合并VO與DTO的說法,舉個例子,User,對應的信息DTO應該是UserInfo,而對應的查詢User的DTO應該是另外一個,通常我用UserSearchCriteria來代替,為什么要把UserInfo和UserSearchCriteria區分開來?你可能認為,UserInfo中大部分屬性,都是可以用于查詢的,所以沒必要弄多一個UserSearchCriteria,但事實上,它們本質上是兩樣東西來的,比如,UserInfo有一個birthday的屬性,但對于查詢來說,系統可能要求查詢某個時間段內出生的User,這個時候,UserSearchCirteria就要定義兩個屬性birthdayFrom,birthdayTo了,所以可以看出,兩者只是“表面上相似”,本質上是兩樣東西,為了設計上的靈活性和擴展性,即使當前情況下兩者的屬性一致,也需要分別進行設計。
對,但頁面查詢用的VO,與表示某個實體的VO不是同一樣東西,如果按我的博文中合并VO與DTO的說法,舉個例子,User,對應的信息DTO應該是UserInfo,而對應的查詢User的DTO應該是另外一個,通常我用UserSearchCriteria來代替,為什么要把UserInfo和UserSearchCriteria區分開來?你可能認為,UserInfo中大部分屬性,都是可以用于查詢的,所以沒必要弄多一個UserSearchCriteria,但事實上,它們本質上是兩樣東西來的,比如,UserInfo有一個birthday的屬性,但對于查詢來說,系統可能要求查詢某個時間段內出生的User,這個時候,UserSearchCirteria就要定義兩個屬性birthdayFrom,birthdayTo了,所以可以看出,兩者只是“表面上相似”,本質上是兩樣東西,為了設計上的靈活性和擴展性,即使當前情況下兩者的屬性一致,也需要分別進行設計。
re: 領域驅動設計系列文章(1)——通過現實例子顯示領域驅動設計的威力 Johnny.Liang 2010-06-29 09:52
@Aidan
聯系方式已經發到你的郵箱,請查收
聯系方式已經發到你的郵箱,請查收
re: 領域驅動設計系列文章(2)——淺析VO、DTO、DO、PO的概念、區別和用處 Johnny.Liang 2010-06-26 00:57
@Aidan
呵呵,謝謝你的持續關注,你這個問題同樣很好,我也曾經被這個問題困擾,你所說的從構造函數傳入,從技術角度來講,是一種可行的辦法,但我不建議這樣做,原因是:
1)DO(即你所說的BO)從業務上來講,不應該與DAO有關聯,因為DAO對于業務來說是沒有意義的,它屬于應用方面的東西。DO構造函數只能包括用于構造它的所必須的元素(我后面的博文會提及)。
2)這樣做會讓DO與你的具體實現耦合,試想,如果某天有某種更好的方法讓你動態注入DAO,意味著你不再需要通過構造函數傳入DAO了,那么你是繼續保留這個參數,還是修改構造函數,從而讓所有調用該構造函數的客戶程序受到影響呢?
事實上,可行的做法有兩種:
1)利用Spring提供的“動態注入”方式,這種方式的原理是,通過一個Annotation,告訴Spring容器,這個DO是需要注入對象的,即需要受到SpringIoC容器管理,那么Spring就會利用“編譯時織入”或“啟動時織入”的技術來為DO的Class類織入注入相關對象的代碼,這種技術依賴于AspectJ,前者更加需要在編譯環境加入AspectJ的增量編譯器,這種方案是相對麻煩的,而且我曾經在OSGi中應用,會出現一些不可預知的問題導致無法注入。
2)在你的應用(通常是Web應用)加載SpringContext的時候,設計一個用于保持SpringContext的ContextHolder,利用某種機制(例如Spring提供的Servlet)來在加載SpringContext的時候,把SpringContext的引用保留在該ContextHolder中,然后在你的DO里面,就可以在實現代碼里面通過ContextHolder提供的靜態方法,獲取到你所需要的Bean了。
呵呵,謝謝你的持續關注,你這個問題同樣很好,我也曾經被這個問題困擾,你所說的從構造函數傳入,從技術角度來講,是一種可行的辦法,但我不建議這樣做,原因是:
1)DO(即你所說的BO)從業務上來講,不應該與DAO有關聯,因為DAO對于業務來說是沒有意義的,它屬于應用方面的東西。DO構造函數只能包括用于構造它的所必須的元素(我后面的博文會提及)。
2)這樣做會讓DO與你的具體實現耦合,試想,如果某天有某種更好的方法讓你動態注入DAO,意味著你不再需要通過構造函數傳入DAO了,那么你是繼續保留這個參數,還是修改構造函數,從而讓所有調用該構造函數的客戶程序受到影響呢?
事實上,可行的做法有兩種:
1)利用Spring提供的“動態注入”方式,這種方式的原理是,通過一個Annotation,告訴Spring容器,這個DO是需要注入對象的,即需要受到SpringIoC容器管理,那么Spring就會利用“編譯時織入”或“啟動時織入”的技術來為DO的Class類織入注入相關對象的代碼,這種技術依賴于AspectJ,前者更加需要在編譯環境加入AspectJ的增量編譯器,這種方案是相對麻煩的,而且我曾經在OSGi中應用,會出現一些不可預知的問題導致無法注入。
2)在你的應用(通常是Web應用)加載SpringContext的時候,設計一個用于保持SpringContext的ContextHolder,利用某種機制(例如Spring提供的Servlet)來在加載SpringContext的時候,把SpringContext的引用保留在該ContextHolder中,然后在你的DO里面,就可以在實現代碼里面通過ContextHolder提供的靜態方法,獲取到你所需要的Bean了。
re: 領域驅動設計系列文章(2)——淺析VO、DTO、DO、PO的概念、區別和用處[未登錄] Johnny.Liang 2010-06-25 20:47
@Aidan
很好的問題,我逐個回答:
1.我所說的不需要password,是值在DTO層面,同一個UserInfo(我在一篇博文中建議以***Info命名DTO,意為***信息),其實對于不同的場景,本質上是不同的,例如,我有個注冊用戶的方法,需要傳入UserInfo,那么逐個DTO必須擁有一些用戶認證或隱私信息的屬性,但對于查詢用戶的方法,它返回的也是一個UserInfo,但這個UserInfo,從需求來說,它不應該包含密碼和隱私信息,那么這兩個雖然都是UserInfo,但理論上應該定義為兩個獨立的DTO,但實際上,這樣做帶來的負面影響會更大,因為我在一個系統中可能要為一個實體定義太多的DTO,所以我建議定義一個包羅萬有的DTO,但在返回數據時,如果有些數據不應該返回,就把屬性設置為null即可,當然SOA中的SDO有另外的做法,這里不詳說,本人也不甚精通。
2.對于VO,DTO,DO,PO的命名,我個人的建議(純屬個人意見),還是不要太過技術化,VO可以叫***View,代表一個”視圖“,DTO用***Info,代表”***的信息“,DO由于是就是業務實體本身,所以直接給它一個釋意名稱,如User、Customer……,至于PO,正如我所說,現在的ORM框架已經可以把這個東西在實現層面通過配置文件(xml)或annonation隱藏起來,所以在實現層面基本不需要存在,如果確實需要的話,我覺得”持久化“本身就是計算機世界的一個非業務領域,這里用技術化命名完全沒有問題,因為它確實是”技術化產物“,在業務領域沒有這個概念。這相信也同樣回答了你在另外一篇博文提出的問題。
希望我的回答能讓你滿意。
很好的問題,我逐個回答:
1.我所說的不需要password,是值在DTO層面,同一個UserInfo(我在一篇博文中建議以***Info命名DTO,意為***信息),其實對于不同的場景,本質上是不同的,例如,我有個注冊用戶的方法,需要傳入UserInfo,那么逐個DTO必須擁有一些用戶認證或隱私信息的屬性,但對于查詢用戶的方法,它返回的也是一個UserInfo,但這個UserInfo,從需求來說,它不應該包含密碼和隱私信息,那么這兩個雖然都是UserInfo,但理論上應該定義為兩個獨立的DTO,但實際上,這樣做帶來的負面影響會更大,因為我在一個系統中可能要為一個實體定義太多的DTO,所以我建議定義一個包羅萬有的DTO,但在返回數據時,如果有些數據不應該返回,就把屬性設置為null即可,當然SOA中的SDO有另外的做法,這里不詳說,本人也不甚精通。
2.對于VO,DTO,DO,PO的命名,我個人的建議(純屬個人意見),還是不要太過技術化,VO可以叫***View,代表一個”視圖“,DTO用***Info,代表”***的信息“,DO由于是就是業務實體本身,所以直接給它一個釋意名稱,如User、Customer……,至于PO,正如我所說,現在的ORM框架已經可以把這個東西在實現層面通過配置文件(xml)或annonation隱藏起來,所以在實現層面基本不需要存在,如果確實需要的話,我覺得”持久化“本身就是計算機世界的一個非業務領域,這里用技術化命名完全沒有問題,因為它確實是”技術化產物“,在業務領域沒有這個概念。這相信也同樣回答了你在另外一篇博文提出的問題。
希望我的回答能讓你滿意。
re: 基于OSGi的Web應用開發系列一(前言) Johnny.Liang 2010-06-19 16:35
@瀟湘振宇
支持原創
支持原創
re: 領域驅動設計系列文章(1)——通過現實例子顯示領域驅動設計的威力 Johnny.Liang 2010-06-03 11:11
@菠蘿大象
Jdon框架采用DDD了么?沒有關注,不過個人覺得不解,DDD主要是針對企業應用的,一個純技術框架,為什么要使用DDD。
Jdon框架采用DDD了么?沒有關注,不過個人覺得不解,DDD主要是針對企業應用的,一個純技術框架,為什么要使用DDD。
re: 開放平臺兩三點感悟 Johnny.Liang 2010-05-29 00:26
謝謝樓主,很不錯,希望多一些這類文章。
re: 領域驅動設計系列文章(1)——通過現實例子顯示領域驅動設計的威力 Johnny.Liang 2010-05-27 16:20
@spell007
您好,這個問題問得非常好,我之前在應用DDD做一個項目的時候,就跟項目成員做過討論,我們發現,DO和Repository(即DAO,我習慣用非技術化命名來讓思維集中與業務而不是技術)兩者是雙向依賴的。原因是:
1)Repository必須依賴DO,因為它要知道DO的數據結構,這無可厚非。
2)為什么DO需要依賴于Repository呢?從實現角度來說,我的賬戶轉賬業務就可以看出這種依賴的存在,另外有些場景,比如有些領域業務邏輯需要查詢一些數據,例如一個Order最多允許10個OrderItem,那么在order.addOrderItem的方法里面,就需要判斷當前Order有多少個OrderItem,這就需要查詢(為了性能不全部加在OrderItem),從設計角度來看,我們想想,在計算機世界,由于DO在大部分情況下是必須持久化的,所以DO從功能上本身就對其Repository存在依賴關系,當然,我們可以只依賴于接口,所以,基于 種種原因,我們不得不讓DO與Repository形成雙向依賴關系。
這個問題值得詳細討論,我會考慮在后面的系列博文增加一篇專門針對這個問題進行分析討論,非常感謝你提出這樣好的問題。
您好,這個問題問得非常好,我之前在應用DDD做一個項目的時候,就跟項目成員做過討論,我們發現,DO和Repository(即DAO,我習慣用非技術化命名來讓思維集中與業務而不是技術)兩者是雙向依賴的。原因是:
1)Repository必須依賴DO,因為它要知道DO的數據結構,這無可厚非。
2)為什么DO需要依賴于Repository呢?從實現角度來說,我的賬戶轉賬業務就可以看出這種依賴的存在,另外有些場景,比如有些領域業務邏輯需要查詢一些數據,例如一個Order最多允許10個OrderItem,那么在order.addOrderItem的方法里面,就需要判斷當前Order有多少個OrderItem,這就需要查詢(為了性能不全部加在OrderItem),從設計角度來看,我們想想,在計算機世界,由于DO在大部分情況下是必須持久化的,所以DO從功能上本身就對其Repository存在依賴關系,當然,我們可以只依賴于接口,所以,基于 種種原因,我們不得不讓DO與Repository形成雙向依賴關系。
這個問題值得詳細討論,我會考慮在后面的系列博文增加一篇專門針對這個問題進行分析討論,非常感謝你提出這樣好的問題。
re: OSGi(Equinox)類加載的問題——使用ClassLoader突破bundle的訪問限制 Johnny.Liang 2010-05-17 12:40
從設計的角度來看,通過了解一些底層機制,繞過OSGi的類加載策略來直接訪問不對外公開的類,不見得是一件好的事情,作為技術研究,了解這些底層機制有助于更熟悉一個框架,以更靈活的運用它,但作為軟件開發,這些做法可能會導致很多隱患和風險,個人認為不值得推崇。
re: 領域驅動設計系列文章(1)——通過現實例子顯示領域驅動設計的威力 Johnny.Liang 2010-05-16 09:47
@何楊
工具有很多,我用的是Enterprise Architecture試用版,還可以用Jude等。
工具有很多,我用的是Enterprise Architecture試用版,還可以用Jude等。
re: Java RMI 入門指南 Johnny.Liang 2010-05-15 00:14
期待你的下一篇博文,特別是關于OSGi,緩存技術的博文
re: “設計”你的代碼 Johnny.Liang 2010-04-30 17:50
@onkyo
明白你的意思,謝謝你的意見,我往后會發表一些針對如何使用面向對象思維進行設計,及其真正的好處的博文,當中就會詳細的說明使用面向對象思維在某些場景中的好處。
明白你的意思,謝謝你的意見,我往后會發表一些針對如何使用面向對象思維進行設計,及其真正的好處的博文,當中就會詳細的說明使用面向對象思維在某些場景中的好處。
re: 編寫高質量的代碼——從命名入手 Johnny.Liang 2010-04-30 12:45
@BearRui(AK-47)
我是這樣想的,做開發人員,基礎英語知識是必備的工具,很多技術文檔、規范、API都是英文的,即使有翻譯,也是讀英語的比較好,因此在我參與過的項目中,包括我曾經工作過的公司,都是嚴禁使用拼音的。
我是這樣想的,做開發人員,基礎英語知識是必備的工具,很多技術文檔、規范、API都是英文的,即使有翻譯,也是讀英語的比較好,因此在我參與過的項目中,包括我曾經工作過的公司,都是嚴禁使用拼音的。
re: 一個非常簡單的例子,反映了很多開發人員的通病 Johnny.Liang 2010-04-29 10:42
@wpskl
前臺驗證主要看需求和用戶體驗,如果希望用戶填寫信息時出現錯誤馬上得到提醒,就需要做前臺校驗,不過現在的軟件強調以用戶為中心(UCD)所以你的做法我是贊同的。
前臺驗證主要看需求和用戶體驗,如果希望用戶填寫信息時出現錯誤馬上得到提醒,就需要做前臺校驗,不過現在的軟件強調以用戶為中心(UCD)所以你的做法我是贊同的。
re: “設計”你的代碼 Johnny.Liang 2010-04-29 09:40
@onkyo
呵呵,回復一下這為同學的兩個評論,首先,你說得對,static就不是面向對象,純面向對象是沒有static函數的,但我要解釋兩點,上面的代碼純屬演示如何改變一種思維方式,我并沒有過于斟酌于代碼的細節,如果要純面向對象的話,我可以把static聲明為對象方法,然后讓這個類變成Singleton;其次,如果所有東西都要考慮繼承的話,就是過度設計對了,正如我在本博文的最后的特別說明,設計是要針對需求的,假如我這個流程相當穩定,不存在多態的情況,那么我就(至少在目前)不需要過度的把它設計為接口,然后再提供實現類,再通過依賴注入,而關于你提到的private方法不能繼承和重用,這也是一個好問題,假如根據實際情況,我不希望我的類或方法被繼承或重寫,我就需要聲明其為final/private了,君不見JDK的很多類都是final的嗎?這同樣也回答了你第二個評論的問題,沒需要多態,或沒需求切換實現,就沒必要接口。
總之,謝謝你的發言,我只能強調,上面的代碼純屬表達一種思維方式,況且,不考慮現實環境和實際需求,孤立的去討論一個類是否有接口,一個方法是否需求繼承,一個靜態方法是否必須設計為對象方法,都是沒有實際意義的,搞不好就是一種“過度設計”。
呵呵,回復一下這為同學的兩個評論,首先,你說得對,static就不是面向對象,純面向對象是沒有static函數的,但我要解釋兩點,上面的代碼純屬演示如何改變一種思維方式,我并沒有過于斟酌于代碼的細節,如果要純面向對象的話,我可以把static聲明為對象方法,然后讓這個類變成Singleton;其次,如果所有東西都要考慮繼承的話,就是過度設計對了,正如我在本博文的最后的特別說明,設計是要針對需求的,假如我這個流程相當穩定,不存在多態的情況,那么我就(至少在目前)不需要過度的把它設計為接口,然后再提供實現類,再通過依賴注入,而關于你提到的private方法不能繼承和重用,這也是一個好問題,假如根據實際情況,我不希望我的類或方法被繼承或重寫,我就需要聲明其為final/private了,君不見JDK的很多類都是final的嗎?這同樣也回答了你第二個評論的問題,沒需要多態,或沒需求切換實現,就沒必要接口。
總之,謝謝你的發言,我只能強調,上面的代碼純屬表達一種思維方式,況且,不考慮現實環境和實際需求,孤立的去討論一個類是否有接口,一個方法是否需求繼承,一個靜態方法是否必須設計為對象方法,都是沒有實際意義的,搞不好就是一種“過度設計”。
re: 一個非常簡單的例子,反映了很多開發人員的通病 Johnny.Liang 2010-04-28 09:07
@問樓上的人
我非常同意你的看法,設計是需求權衡的,設計是一種選擇,我寫這篇博文是發現很多開發人員沒有這種思想,并不是一刀切的要求都必須按設計方式生搬硬套。謝謝你的意見。
我非常同意你的看法,設計是需求權衡的,設計是一種選擇,我寫這篇博文是發現很多開發人員沒有這種思想,并不是一刀切的要求都必須按設計方式生搬硬套。謝謝你的意見。