領域模型的概念

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

概念是如何被偷換的呢?請注意,領域模型(Domain Model)是一個商業建模範疇的概念,他和軟件開發並無一絲一毫的關係,即使一個企業他不開發軟件,他也具備他的業務模型,所有的同行業的企業他們的業務模型必定有非常大的共性和內在的規律性,由這個行業內的各個企業的業務模型再向上抽象出來整個行業的業務模型,這個東西即“領域模型”。一個掌握了行業領域模型的軟件公司,根本不需要再給人家開發項目了,根本不需要靠軟件開發養活自己了,你光給這個行業的企業提供業務諮詢已經賺得非常豐厚的利潤了。以我現在兼職所在的公司來說,就是這樣一家軟件公司,在行業內積累了足夠的領域模型,成立了一個專門的諮詢部門,這個部門下面都是諮詢師,他們是不管軟件開發的,也不懂軟件開發,他們就專門教這個行業的客戶,教他們怎麼去做自己的業務,他們比客戶還精通客戶的業務,光是業務諮詢已經可以爲公司帶來很多的收入。

而軟件開發呢?一個並沒有行業經驗積累的軟件公司,它開發的軟件,基本上完全是需求驅動,而不是領域模型驅動。只有具備了領域模型積累的公司纔有資格去談領域模型驅動軟件開發。在由領域模型往某種編程語言如Java上來實現的時候,絕對不會是1:1的對應關係,即使是粗顆粒度的EJB2模型都做不到,更不要說更加強調細顆粒度的POJO模型呢?用面向對象的語言如Java來編寫一個領域模型,如果是用EJB2模型,你需要使用最少兩個以上的EJB,即一個 Session Bean,處理面向流程的控制邏輯,一個Entity Bean,處理面向持久化的實體邏輯(持久化操作附着在Entity Bean的Home接口上)。如果是更加複雜的領域模型,那麼你需要更多的EJB,也許是一個領域模型需要多個Entity Bean和多個Session Bean。現在我們使用基於POJO模型的實現,那麼粗顆粒度的EJB還要繼續細分:一個Entity Bean要剝離出來至少三個以上的POJO,即一個或者多個實體類,一個或者多個DAO接口類,一個或者多個DAO接口實現類;一個Session Bean要切分爲多個業務Bean。

由此我們終於看出來概念是怎樣被偷換的了,一個商業概念的抽象領域模型被一個Java持久化實體類替代了。但是我們應該看到,Martin批評的貧血的領域模型並不是Hibernate實體類,Martin指的貧血的領域模型實際上是缺乏豐富業務邏輯概念的領域抽象模型,這和Hibernate實體類完全是風牛馬不相及的東西。而Hibernate實體類只是具體編碼過程中,爲了實現一個領域模型而編寫的一組基於POJO的對象中的,完成領域模型某個特徵的類。而這個領域模型完整的特徵並不應該,也不可能由一個非常粗顆粒度的單類完成,而是由一組互相協作的類完成:即Hibernate的實體類保持領域模型的狀態;DAO接口實現類完成領域模型的持久化操作;Spring Bean類完成領域模型的邏輯控制功能。

 


 

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

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

我沒有看過Martin的DDD,我按照自己的理解, POJO domain models指的就是輕量級的領域模型。何爲輕量級? 把領域模型的各個特徵,各個屬性,各個邏輯都塞到一個class裏面叫做輕量級嗎?

我認爲,Martin批評的貧血的領域模型是指只關注了領域模型持久化特徵方面,而忽略了領域模型其他特徵方面的模型,這樣的模型是貧血的。因爲這種模型只關注了模型在技術層面的外在表現,也就是說只關注了數據的存取操作,而忽視了模型蘊含的業務核心價值。

舉例來說,我們編一個銀行軟件,如果你只關注了賬戶的增刪改查,這叫做貧血!而實際上你應該關注的是賬戶的業務特徵,而不是數據特徵,你應該關注的是賬號開立的業務,賬戶註銷的業務,賬號過戶的業務等等,這纔是領域模型。這種領域模型在一個單純的技術實現層面來說,對於最簡單的業務,你可能只是Account類的增刪改查,但是對於複雜的業務來說,他就不單但是一個類,一個表的簡單操作了,例如開立賬戶,你要收手續費,以及考察個人財務狀況,那麼此時你需要的就是一組協作的類。

Martin提到領域模型,意在強調我們應該關注軟件的業務,關注行業知識的內在規律,並且把這種規律建模爲領域模型,批評拿到一個軟件,腦子裏面光想到數據庫增刪改查的人。這和我們的Hibernate持久化類毫無關係!

我的看法是:一個抽象的領域模型具備多方面的特徵,你需要用一組互相協作的類來完成它,每一個或者一組類承擔這個領域模型的某個特徵。例如某個領域模型,例如上面的賬戶,你需要一組Hibernate持久化類:包括Account類,User類,Finance類,一組SpringBean類,AccountManager,FinanceManager,一組DAO接口和實現類。由這些POJO的類互相協作來共同完成這個領域模型。如果你僅僅關注Account的增刪改查,那就貧血了,而如果你關注了賬戶的業務規則,並且考慮一組互相協作的類去完成它,就不是貧血的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章