現在的問題
現在我們J2EE開發(fā)碰到了什么問題呢? 讓我們想象一下使用Spring和Hibernate開發(fā)一個J2EE WEB應用是什么樣的:我們需要增加一個新的域對象類型為Person,下面主要的開發(fā)步驟:
- 創(chuàng)建
Person
類. - 創(chuàng)建
PersonDAO
類. - 創(chuàng)建
Person數據表
. - 定義
PersonDAO在
Spring的application context XML文件. - 創(chuàng)建
Person
page頁面和action類. - 增加
Person頁面到
web框架(如struts)XML配置文件中. - 創(chuàng)建
personList
頁面來顯示Person實例
. - 創(chuàng)建
personEdit
頁面來編輯Person
實例.
你會確實感慨:真是需要很多步驟啊。
如何解決?
關鍵問題是我們開發(fā)時不能重復一些步驟,因此必須盡量減少步驟,如果只減少步驟到:
- 創(chuàng)建
Person
類?
是否只需要第一個步驟就可以?在第一步時,我們花費更多時間精力進行域建模,確定域模型的屬性行為等。其他步驟我們會發(fā)現下面的規(guī)律:
- 對于每個實體,我們需要完成應用的基本功能,如 create, retrieve, update, and delete (CRUD).
- 我們需要每個實體持久化到數據庫.
- 我們需要數據庫為每個實體創(chuàng)建數據表。
- 我們需要安排實體之間的關系。
當然,在復雜應用中,不會只是這些功能,但是如果我們將這些功能通過框架實現,將大大提高我們的開發(fā)效率。
域驅動開發(fā)
域驅動開發(fā)(domain driven development framework ),簡稱DDD是一種最新的OO設計概念,它是由ROR和Naked Object組織提出的。
所謂naked Object是指一個復雜的域對象,這個Object是一個POJO,但是不是一個傻傻的完全是屬性的POJO,而是封裝了業(yè)務邏輯的POJO,注意這里是最大的區(qū)別,一般業(yè)務邏輯我們是通過另外的Service類來實現,然后在Service中封裝的transaction script(Martin Fowler卻稱為貧血模型) , naked Object則是合并起來的(有的類似回歸傳統(tǒng)了,符合Martin Fowler審美觀了),但是,這種純OO是和SOA()思想矛盾的(Service-Oriented vs. Object-Oriented ),可見Adventures in SOA(puts the business logic in service-like methods instead of on the object, service method -> business method --> persistence method) )
個人感覺整個軟件好像一直在玩0或1的游戲,不過也許最復雜的體系就是來自最簡單的抉擇,如股票/匯市等投資領域也如此。
naked Object提出現在J2EE開發(fā)和裸體對象DDD開發(fā)下的圖:
通過這張圖我們可以看到,以前方式造成J2EE開發(fā)層次之間調用混亂,修改和拓展非常不方便,而在右邊的DDD開發(fā)方式下,界面(邊界)對象就是域對象就是持久化的實體BO,沒有多余的Contorller或Action了。原來Domain層被服務層Service layer遮擋,在右圖中,則Domain層直接暴露給前臺了,所以Domain沒有東西被遮蓋,裸露了,稱為Naked(裸露) Objects.
現在怎么辦?
ROR提倡的DDD方式引起了眾多J2EE開發(fā)者的興趣,在各大Java媒體正在引起廣泛的討論,但是ROR不是Java的,那么有無基于Java的DDD開發(fā)框架呢?
目前有不少DDD開發(fā)框架正在誕生中,Jdon框架正是在ROR這種精神指引下的一款快速開源開發(fā)框架,Jdon框架1.2.2版本雖然不是一個完全意義上的Naked Object,基于Service-Oriented 架構,但是已經初步具備上圖右邊開發(fā)流程,具體可參考Jdon Sample的開發(fā)流程
使用Jdon框架開發(fā)J2EE應用系統(tǒng),最重要的一個前提是:設計好你的域對象,然后在將域對象復制到表現層,變成表現層的ActionForm/ModelForm;將域對象直接在持久層使用Hibernate/iBatis等持久化到數據庫;如果使用EJB的實體Bean持久化技術,將無需實現建立數據表;應用系統(tǒng)部署時,J2EE容器將直接根據實體建立數據表,也可節(jié)省前面步驟中兩個步驟。
當然,目前Jdon框架是采取分離手法,遵循橋模式,將抽象和行為分離,每個域對象對應一個操作它的服務類或DAO類,服務類主要用來封裝業(yè)務邏輯層,然后將業(yè)務Service作為一個業(yè)務組件暴露給表現層的Controller/Action類,而Controller/Action則無需代碼,只要通過如下配置即可完成:
<model key="username" class="com.jdon.framework.samples.jpetstore.domain.Account">
<actionForm name="accountForm"/> //指定邊界類
<handler>
<service ref="accountService"> //指定某個業(yè)務接口
<getMethod name="getAccount"/>
<createMethod name="insertAccount"/> //業(yè)務接口的新增方法
<updateMethod name="updateAccount"/> //業(yè)務接口的修改方法
<deleteMethod name="deleteAccount"/>
</service>
</handler>
</model>
通過上述配置,凈化了上圖中應用控制層(Application or Controller layer)和Domain Layer之間對應關系,變得有條理而且明晰。
隨著Naked Object 被越來越多人認識和應用成熟,Jdon框架也將轉向支持另外一個純OO流派Naked Object, 就象它同時支持POJO派和EJB派一樣。
在Jdon框架以后版本中,會很方便支持Naked Object,只要將上面配置文件指向Service去除,CRUD方法由Model自己實現,如下:
<model key="username" class="com.jdon.framework.samples.jpetstore.domain.Account">
<actionForm name="accountForm"/> //指定邊界類
<handler>
<!-- <service ref="accountService"> //指定某個業(yè)務接口 無需業(yè)務層,去除-->
<getMethod name="getAccount"/>
<createMethod name="insertAccount"/> //業(yè)務接口的新增方法
<updateMethod name="updateAccount"/> //業(yè)務接口的修改方法
<deleteMethod name="deleteAccount"/>
<!-- </service> -->
</handler>
</model>