轉載于http://www.tkk7.com/wadise/archive/2005/12/16/24209.html
在Martin Fowler文章http://www.martinfowler.com/bliki/AnemicDomainModel.html中指出現在出現越來越多的貧血領域模型(anemia domain model)。那么貧血領域模型的概念是什么呢?老馬指出:
There are objects, many named after the nouns in the domain space, and these objects are connected with the rich relationships and structure that true domain models have. The catch comes when you look at the behavior, and you realize that there is very little behavior on these objects. Indeed often these models come with design rules that say that you are not to put any domain logic in the the domain objects. Instead there are a set of service objects which capture all the domain logic. These services live on top of the domain model and use the domain model for data.
也就是說在領域模型中,本身只處理很少的行為邏輯,大多數都是處在模型上層的一系列的Service類來負責捕獲處理這些領域邏輯行為。這違背了OO思想(OO認為應該把數據和行為合在一起)。
Eric Evans在他的Domain Driven Design中說過:
Application Layer [his name for Service Layer]: Defines the jobs the software is supposed to do and directs the expressive domain objects to work out problems. The tasks this layer is responsible for are meaningful to the business or necessary for interaction with the application layers of other systems. This layer is kept thin. It does not contain business rules or knowledge, but only coordinates tasks and delegates work to collaborations of domain objects in the next layer down. It does not have state reflecting the business situation, but it can have state that reflects the progress of a task for the user or the program.
Domain Layer (or Model Layer): Responsible for representing concepts of the business, information about the business situation, and business rules. State that reflects the business situation is controlled and used here, even though the technical details of storing it are delegated to the infrastructure. This layer is the heart of business software.
據說在Thoughtwork公司里面采用的技術是Hibernate+Spring+webwork,關于anemia domain model有不少員工在公司內部郵件中發問老馬應該什么正確使用。但是老馬還沒有給出確切答案,只放入TODOList去。
我個人覺的Domail類中不應該含有過多的與之無關的行為,不但違反了單一職責的原則,還使得整個系統不夠穩定。例如User中有Roles,那么addRole,removeRole自然應在Domain類User中寫,至于removeUser,loadUser等應該封裝成Dao去處理。
引用robbin在一次討論中的回復:
我的理解是Martin大叔所謂的domain object是“領域模型”,它是一個針對業務邏輯抽象的模型,和軟件編程根本毫無關系。即使你不開發這個軟件,你仍然需要抽象你的業務邏輯得到你的領域模型。這個領域指的是你所從事的行業,而不是狹隘的持久化類。
并且領域模型的建模也是在需求分析階段,或者在需求分析階段之前完成的事情。具體到編程的過程中,領域模型并非對應某一個Java類,如果一定要強行對應的話,(業務對象,Dao接口,Hibernate實體類)他們合起來統稱領域模型在Java語言的實現。把 商業建模范疇的“領域模型”拿來當做Hibernate編程中的實體類,根本就是牛頭不對馬嘴!
其實你的主張就是把持久化實體類的持久化操作附著到實體類上面去,而不是分開。舉例來說,也就是說Account類的增刪改查不應該單獨分離到AccountDao接口去,而應該把增刪改查操作放在Account類里面來完成,對不?
那么我在解釋這個問題之前,必須澄清一點,就是這個問題的討論,即持久化操作是否應該單獨抽象一個DAO層的問題是和Martin Fowler提到了貧血的領域模型毫無關系的。實際上傳統的Entity Bean就是這種把持久化操作附著到Entity Bean本身去的,但是Martin Fowler一樣在說,這種Entity Bean就是貧血的。
好了,我們現在把其他無關因素排除了,focus到這個話題上,就是我們是否需要DAO接口的問題了。因為按照你的觀點,如果把對象的增刪改查都放在實體類上面,其實我們就不需要DAO接口層了,業務對象和Web Action都可以直接調用實體類本身來完成持久化操作了。
大概在2003年以前,我一直就是采用這種模型的,但是從2003年開始,我就改成了分離一個DAO層來專門處理持久化操作了。原因是多方面的,從技術角度來考量的話,分離就有很多好處,Rod Johnson在《without EJB》第10章持久化里面就詳細闡述了需要DAO層的理由,我建議你看一下,這里不復述了。只談一下除了Rod Johson提到理由之外的理由:
作為保持狀態的實體類,他的職責是保持狀態,而不負責狀態的持久化。如果把持久化操作也放在實體類中,一方面來說,把兩種不同的職責放在一個類中,并不符合OCP的單一職責的原則,然而更重要的原因是會帶來實體類的不穩定的問題。
在我的理念中,實體類以及實體類關聯關系是一個軟件系統中最穩定不變的部分,在整個軟件系統中,各個層面都需要涉及到實體類的操作,如何劃分實體類,以及確定實體類關聯是最費考量的,確定了這一點,整個軟件系統就底層依賴關系就被確定下來了(實體類的屬性可以變化,由于軟件系統對實體的操作都是以實體類為單位的,所以實體屬性的變化不會造成系統不穩定),上面的DAO層,業務層,Web層都只對實體類產生單向依賴。
如果你把DAO層合并到實體類中,請注意本來Web層是不依賴于DAO層的,Web層只依賴實體類(因為它要展現實體類狀態),但是由于你合并了,使得Web層也變得依賴那些DAO層的操作了。這樣的結果就是讓軟件系統的耦合性提高,可伸縮性降低,可維護性降低。
DAO層的變動是大于實體類變動的,實體類基本上穩定不變,而軟件系統的需求變更幾乎一定會帶來DAO層的變動,但是并不會帶來實體類層的變動(會帶來實體屬性的變動,但是很少會影響到實體類本身)。所以DAO層的變動頻率遠遠大于實體類。那么當你把DAO層操作合并到實體類以后,其結果就是讓實體類的變動頻率等于DAO層的變動頻率。那么就會造成本來穩定的實體類層變得變得頻率高了很多,而實體類的變動會波及到軟件系統的每個層面,造成軟件大面積的相關性和不穩定。
請記住很重要的一點:實體類是有狀態的類,DAO類是無狀態的類,在整個軟件系統中,只有兩種類有狀態,一個是實體類,一個是HTTP Session。有狀態的類會帶來很高的代碼相關性,應該盡量減少有狀態類的影響范圍,盡量減少有狀態類的變動頻率,應該盡量減少有狀態類的職責。
而你把DAO操作合并到實體類以后,結果就是擴大了有狀態類的代碼相關性的范圍和影響范圍,擴大了有狀態類的變動頻率,最后就造成軟件系統的穩定性下降。
posted on 2009-08-30 17:41
zhqh 閱讀(170)
評論(0) 編輯 收藏 所屬分類:
面向對象