2020国产成人精品视频,性做久久久久久久久,亚洲国产成人久久综合一区,亚洲影院天堂中文av色

分享

領(lǐng)域模型的概念

 jiashengfan 2006-07-18

領(lǐng)域模型的概念

自從Martin Fowler的DDD(Domain Driven Develop 領(lǐng)域驅(qū)動(dòng)開發(fā))提出來之后,無數(shù)的人就開始非議ORM方式下的持久化實(shí)體類,抨擊這種方式下的實(shí)體類是“貧血”的,缺乏豐富業(yè)務(wù)語義的。其實(shí)他們都犯了一個(gè)最基本的邏輯錯(cuò)誤 - 偷換概念。

概念是如何被偷換的呢?請(qǐng)注意,領(lǐng)域模型(Domain Model)是一個(gè)商業(yè)建模范疇的概念,他和軟件開發(fā)并無一絲一毫的關(guān)系,即使一個(gè)企業(yè)他不開發(fā)軟件,他也具備他的業(yè)務(wù)模型,所有的同行業(yè)的企業(yè)他們的業(yè)務(wù)模型必定有非常大的共性和內(nèi)在的規(guī)律性,由這個(gè)行業(yè)內(nèi)的各個(gè)企業(yè)的業(yè)務(wù)模型再向上抽象出來整個(gè)行業(yè)的業(yè)務(wù)模型,這個(gè)東西即“領(lǐng)域模型”。一個(gè)掌握了行業(yè)領(lǐng)域模型的軟件公司,根本不需要再給人家開發(fā)項(xiàng)目了,根本不需要靠軟件開發(fā)養(yǎng)活自己了,你光給這個(gè)行業(yè)的企業(yè)提供業(yè)務(wù)咨詢已經(jīng)賺得非常豐厚的利潤(rùn)了。以我現(xiàn)在兼職所在的公司來說,就是這樣一家軟件公司,在行業(yè)內(nèi)積累了足夠的領(lǐng)域模型,成立了一個(gè)專門的咨詢部門,這個(gè)部門下面都是咨詢師,他們是不管軟件開發(fā)的,也不懂軟件開發(fā),他們就專門教這個(gè)行業(yè)的客戶,教他們?cè)趺慈プ鲎约旱臉I(yè)務(wù),他們比客戶還精通客戶的業(yè)務(wù),光是業(yè)務(wù)咨詢已經(jīng)可以為公司帶來很多的收入。

而軟件開發(fā)呢?一個(gè)并沒有行業(yè)經(jīng)驗(yàn)積累的軟件公司,它開發(fā)的軟件,基本上完全是需求驅(qū)動(dòng),而不是領(lǐng)域模型驅(qū)動(dòng)。只有具備了領(lǐng)域模型積累的公司才有資格去談?lì)I(lǐng)域模型驅(qū)動(dòng)軟件開發(fā)。在由領(lǐng)域模型往某種編程語言如Java上來實(shí)現(xiàn)的時(shí)候,絕對(duì)不會(huì)是1:1的對(duì)應(yīng)關(guān)系,即使是粗顆粒度的EJB2模型都做不到,更不要說更加強(qiáng)調(diào)細(xì)顆粒度的POJO模型呢?用面向?qū)ο蟮恼Z言如Java來編寫一個(gè)領(lǐng)域模型,如果是用EJB2模型,你需要使用最少兩個(gè)以上的EJB,即一個(gè) Session Bean,處理面向流程的控制邏輯,一個(gè)Entity Bean,處理面向持久化的實(shí)體邏輯(持久化操作附著在Entity Bean的Home接口上)。如果是更加復(fù)雜的領(lǐng)域模型,那么你需要更多的EJB,也許是一個(gè)領(lǐng)域模型需要多個(gè)Entity Bean和多個(gè)Session Bean?,F(xiàn)在我們使用基于POJO模型的實(shí)現(xiàn),那么粗顆粒度的EJB還要繼續(xù)細(xì)分:一個(gè)Entity Bean要?jiǎng)冸x出來至少三個(gè)以上的POJO,即一個(gè)或者多個(gè)實(shí)體類,一個(gè)或者多個(gè)DAO接口類,一個(gè)或者多個(gè)DAO接口實(shí)現(xiàn)類;一個(gè)Session Bean要切分為多個(gè)業(yè)務(wù)Bean。

由此我們終于看出來概念是怎樣被偷換的了,一個(gè)商業(yè)概念的抽象領(lǐng)域模型被一個(gè)Java持久化實(shí)體類替代了。但是我們應(yīng)該看到,Martin批評(píng)的貧血的領(lǐng)域模型并不是Hibernate實(shí)體類,Martin指的貧血的領(lǐng)域模型實(shí)際上是缺乏豐富業(yè)務(wù)邏輯概念的領(lǐng)域抽象模型,這和Hibernate實(shí)體類完全是風(fēng)牛馬不相及的東西。而Hibernate實(shí)體類只是具體編碼過程中,為了實(shí)現(xiàn)一個(gè)領(lǐng)域模型而編寫的一組基于POJO的對(duì)象中的,完成領(lǐng)域模型某個(gè)特征的類。而這個(gè)領(lǐng)域模型完整的特征并不應(yīng)該,也不可能由一個(gè)非常粗顆粒度的單類完成,而是由一組互相協(xié)作的類完成:即Hibernate的實(shí)體類保持領(lǐng)域模型的狀態(tài);DAO接口實(shí)現(xiàn)類完成領(lǐng)域模型的持久化操作;Spring Bean類完成領(lǐng)域模型的邏輯控制功能。

 


 

POJO指的就是非EJB那種重量級(jí),高侵入性的組件模型,關(guān)于POJO的定義,你同樣可以在Martin Fowler的bliki上面找到。

Spring的Bean是不是POJO? 是的!
Hibernate的entity是不是POJO?是的!
DAO接口是不是POJO?是的!
EJB是不是POJO? 不是的!

我沒有看過Martin的DDD,我按照自己的理解, POJO domain models指的就是輕量級(jí)的領(lǐng)域模型。何為輕量級(jí)? 把領(lǐng)域模型的各個(gè)特征,各個(gè)屬性,各個(gè)邏輯都塞到一個(gè)class里面叫做輕量級(jí)嗎?

我認(rèn)為,Martin批評(píng)的貧血的領(lǐng)域模型是指只關(guān)注了領(lǐng)域模型持久化特征方面,而忽略了領(lǐng)域模型其他特征方面的模型,這樣的模型是貧血的。因?yàn)檫@種模型只關(guān)注了模型在技術(shù)層面的外在表現(xiàn),也就是說只關(guān)注了數(shù)據(jù)的存取操作,而忽視了模型蘊(yùn)含的業(yè)務(wù)核心價(jià)值。

舉例來說,我們編一個(gè)銀行軟件,如果你只關(guān)注了賬戶的增刪改查,這叫做貧血!而實(shí)際上你應(yīng)該關(guān)注的是賬戶的業(yè)務(wù)特征,而不是數(shù)據(jù)特征,你應(yīng)該關(guān)注的是賬號(hào)開立的業(yè)務(wù),賬戶注銷的業(yè)務(wù),賬號(hào)過戶的業(yè)務(wù)等等,這才是領(lǐng)域模型。這種領(lǐng)域模型在一個(gè)單純的技術(shù)實(shí)現(xiàn)層面來說,對(duì)于最簡(jiǎn)單的業(yè)務(wù),你可能只是Account類的增刪改查,但是對(duì)于復(fù)雜的業(yè)務(wù)來說,他就不單但是一個(gè)類,一個(gè)表的簡(jiǎn)單操作了,例如開立賬戶,你要收手續(xù)費(fèi),以及考察個(gè)人財(cái)務(wù)狀況,那么此時(shí)你需要的就是一組協(xié)作的類。

Martin提到領(lǐng)域模型,意在強(qiáng)調(diào)我們應(yīng)該關(guān)注軟件的業(yè)務(wù),關(guān)注行業(yè)知識(shí)的內(nèi)在規(guī)律,并且把這種規(guī)律建模為領(lǐng)域模型,批評(píng)拿到一個(gè)軟件,腦子里面光想到數(shù)據(jù)庫(kù)增刪改查的人。這和我們的Hibernate持久化類毫無關(guān)系!

我的看法是:一個(gè)抽象的領(lǐng)域模型具備多方面的特征,你需要用一組互相協(xié)作的類來完成它,每一個(gè)或者一組類承擔(dān)這個(gè)領(lǐng)域模型的某個(gè)特征。例如某個(gè)領(lǐng)域模型,例如上面的賬戶,你需要一組Hibernate持久化類:包括Account類,User類,F(xiàn)inance類,一組SpringBean類,AccountManager,F(xiàn)inanceManager,一組DAO接口和實(shí)現(xiàn)類。由這些POJO的類互相協(xié)作來共同完成這個(gè)領(lǐng)域模型。如果你僅僅關(guān)注Account的增刪改查,那就貧血了,而如果你關(guān)注了賬戶的業(yè)務(wù)規(guī)則,并且考慮一組互相協(xié)作的類去完成它,就不是貧血的。

 


 

竊以為,這是這段時(shí)間搜尋的領(lǐng)域模型概念的最合拍的解釋了。。

另外還有這兩篇
總結(jié)一下最近關(guān)于domain object以及相關(guān)的討論

再次小結(jié)領(lǐng)域模型的種種觀點(diǎn)


 


 


從技術(shù)手段來上說,對(duì)于Spring/Hibernate架構(gòu),Martin的Rich domin model變得可行了,那么讓我們看看究竟有哪些領(lǐng)域模型,以及他們的優(yōu)缺點(diǎn):

一、失血模型

失血模型請(qǐng)看
http://forum./viewtopic.php?t=11712
中列舉的第一種模型,簡(jiǎn)單來說,就是domain object只有屬性的getter/setter方法,沒有任何業(yè)務(wù)邏輯。

二、貧血模型

貧血模型請(qǐng)看
http://forum./viewtopic.php?t=11712
中列舉的第二種模型,簡(jiǎn)單來說,就是domain ojbect包含了不依賴于持久化的領(lǐng)域邏輯,而那些依賴持久化的領(lǐng)域邏輯被分離到Service層。
Service(業(yè)務(wù)邏輯,事務(wù)封裝) --> DAO ---> domain object

這種模型的優(yōu)點(diǎn):
1、各層單向依賴,結(jié)構(gòu)清楚,易于實(shí)現(xiàn)和維護(hù)
2、設(shè)計(jì)簡(jiǎn)單易行,底層模型非常穩(wěn)定
這種模型的缺點(diǎn):
1、domain object的部分比較緊密依賴的持久化domain logic被分離到Service層,顯得不夠OO
2、Service層過于厚重

三、充血模型
充血模型和第二種模型差不多,所不同的就是如何劃分業(yè)務(wù)邏輯,即認(rèn)為,絕大多業(yè)務(wù)邏輯都應(yīng)該被放在domain object里面(包括持久化邏輯),而Service層應(yīng)該是很薄的一層,僅僅封裝事務(wù)和少量邏輯,不和DAO層打交道。
Service(事務(wù)封裝) ---> domain object <---> DAO

這種模型的優(yōu)點(diǎn):
1、更加符合OO的原則
2、Service層很薄,只充當(dāng)Facade的角色,不和DAO打交道。
這種模型的缺點(diǎn):
1、DAO和domain object形成了雙向依賴,復(fù)雜的雙向依賴會(huì)導(dǎo)致很多潛在的問題。
2、如何劃分Service層邏輯和domain層邏輯是非常含混的,在實(shí)際項(xiàng)目中,由于設(shè)計(jì)和開發(fā)人員的水平差異,可能導(dǎo)致整個(gè)結(jié)構(gòu)的混亂無序。
3、考慮到Service層的事務(wù)封裝特性,Service層必須對(duì)所有的domain object的邏輯提供相應(yīng)的事務(wù)封裝方法,其結(jié)果就是Service完全重定義一遍所有的domain logic,非常煩瑣,而且Service的事務(wù)化封裝其意義就等于把OO的domain logic轉(zhuǎn)換為過程的Service TransactionScript。該充血模型辛辛苦苦在domain層實(shí)現(xiàn)的OO在Service層又變成了過程式,對(duì)于Web層程序員的角度來看,和貧血模型沒有什么區(qū)別了。

四、脹血模型
基于充血模型的第三個(gè)缺點(diǎn),有同學(xué)提出,干脆取消Service層,只剩下domain object和DAO兩層,在domain object的domain logic上面封裝事務(wù)。
domain object(事務(wù)封裝,業(yè)務(wù)邏輯) <---> DAO
似乎ruby on rails就是這種模型,他甚至把domain object和DAO都合并了。
該模型優(yōu)點(diǎn):
1、簡(jiǎn)化了分層
2、也算符合OO
該模型缺點(diǎn):
1、很多不是domain logic的service邏輯也被強(qiáng)行放入domain object ,引起了domain ojbect模型的不穩(wěn)定
2、domain object暴露給web層過多的信息,可能引起意想不到的副作用。

在這四種模型當(dāng)中,失血模型和脹血模型應(yīng)該是不被提倡的。而貧血模型和充血模型從技術(shù)上來說,都已經(jīng)是可行的了。但是我個(gè)人仍然主張使用貧血模型。其理由:

1、參考充血模型第三個(gè)缺點(diǎn),由于暴露給web層程序拿到的還是Service Transaction Script,對(duì)于web層程序員來說,底層OO意義喪失了。

2、參考充血模型第三個(gè)缺點(diǎn),為了事務(wù)封裝,Service層要給每個(gè)domain logic提供一個(gè)過程化封裝,這對(duì)于編程來說,做了多余的工作,非常煩瑣。

3、domain object和DAO的雙向依賴在做大項(xiàng)目中,考慮到團(tuán)隊(duì)成員的水平差異,很容易引入不可預(yù)知的潛在bug。

4、如何劃分domain logic和service logic的標(biāo)準(zhǔn)是不確定的,往往要根據(jù)個(gè)人經(jīng)驗(yàn),有些人就是覺得某個(gè)業(yè)務(wù)他更加貼近domain,也有人認(rèn)為這個(gè)業(yè)務(wù)是貼近service的。由于劃分標(biāo)準(zhǔn)的不確定性,帶來的后果就是實(shí)際項(xiàng)目中會(huì)產(chǎn)生很多這樣的爭(zhēng)議和糾紛,不同的人會(huì)有不同的劃分方法,最后就會(huì)造成整個(gè)項(xiàng)目的邏輯分層混亂。這不像貧血模型中我提出的按照是否依賴持久化進(jìn)行劃分,這種標(biāo)準(zhǔn)是非常確定的,不會(huì)引起爭(zhēng)議,因此團(tuán)隊(duì)開發(fā)中,不會(huì)產(chǎn)生此類問題。

5、貧血模型的domain object確實(shí)不夠rich,但是我們是做項(xiàng)目,不是做研究,好用就行了,管它是不是那么純的OO呢?其實(shí)我不同意firebody認(rèn)為的貧血模型在設(shè)計(jì)模型和實(shí)現(xiàn)代碼中有很大跨越的說法。一個(gè)設(shè)計(jì)模型到實(shí)現(xiàn)的時(shí)候,你直接得到兩個(gè)類:一個(gè)實(shí)體類,一個(gè)控制類就行了,沒有什么跨越。

 

 

 


 

這邊提到ruby on rails,屬于脹血模型,因?yàn)樗裠omain object和DAO都合并了。
竊以為RoR是居于表模塊+活動(dòng)記錄,與JAVA適合的情況有些不同。采用活動(dòng)記錄的架構(gòu),在持久化的時(shí)候,語法貌似更OO些,是直接obj.save()這樣,而不是DAO,save(obj)

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多