暴露領域模型的不均勻性(中國IT讀懂此文的不超過十個人)

GUANPEI發表於2008-07-05
暴露領域模型(Exposed Domain Model)的不均勻性――一個問題引發的思考
一個簡單的問題
物件關係對映持久化引擎提供了弱型別的查詢OQL,一個業務實體Person,現在要查詢名字為**的人。模型層有兩個可能做法:

1.傳統的Service-DAO: getPersonByName(String name)
2.由上層直接使用持久化引擎
問題本身雖然簡單,但是不同的選擇會反映出很深刻的方法論的傾向性。本文對它們作一些辨析。

深度暴露
上述問題的第二種處理方法實際上將物件導向的持久化引擎直接暴露給表現層(或者是邏輯層的最上部),第一種方法是對持久化引擎作了簡單的封裝;問題在於,這種封裝過分降低了通用性,基本上是與功能用例形成對應關係,其後果是導致大量的無任何抽象性可言的垂直邏輯單元;它們隨著功能的增加線性膨脹。第一種方案直接將持久化引擎(實際上是持久化引擎的一個很薄的封裝)暴露出來,而持久化引擎提供了對業務實體最直接的訪問能力,是一種最深層次的暴露。功能用例直接接觸深層模型。

物件導向查詢語言
第一種方案使系統的上部直接面向弱型別的物件導向查詢語言而不是具有明確的語義的服務介面,其合理性問題需要一個像樣的解釋。首先,物件導向查詢語言無論在語法結構上與SQL看起來如何相似,從概念模型的角度,它與SQL都有本質的區別:OQL所面向的是業務實體及其關聯關係所形成的領域模型的靜態結構,SQL所面向的是關係表;業務實體及其關係集中了兩個成果:第一,物件關係對映引擎在抽象的、通用的、領域無關的層面上、語法的層面上所做的轉化;第二,實體及其關聯關係所反映的抽象的領域模型。如另外一篇文章所述,這個模型實際上是完整的領域模型的靜態方面。這個模型的產生集中體現了設計活動的基礎形成果。現實的開發者經常需要完成一種專案改造,將一個直接面向關係表構造行為邏輯的系統改造為透過物件關係對映構造行為邏輯的系統;如果一個開發者做過這種種遺留系統的改造,應該對這兩點有所體會。物件關係對映工具所提供的由表結構到類的對映工具所得到的型別系統基本無法以一種直觀的方式體現業務物件的關係,改造者需要經過大量的調整,在業務物件和遺留系統資料庫模式之間建立曲折複雜的而不是直接的對映關係之後,物件層才能夠呈現出業務邏輯概念模型;這種調整將佔去改造工作的一半以上的工作量,從而也蘊含了一半以上的設計努力;業務實體及其關係在很大程度上基本反映出領域模型。透過OQL所操作的正是這樣一個領域靜態模型。

對領域靜態模型的操作由模型本身來完成的時候,這種操作就內化為模型的行為,這也是物件導向的一個基礎的概念:封裝,使資訊及其之上的邏輯合一。如同任何方法論一樣,物件導向的封裝概念同樣有自己得適用條件,從而也會因為系統構造者的習慣、風格、價值觀等因素的差異引發分歧;在客觀上,封裝的必要性問題也是一個連續的譜系,這個譜系的座標軸就是:所封裝的邏輯的強弱。邏輯越強,蘊含了相當的原子操作的組合操作時,封裝是必要的,如果是不具有任何組合性質的讀、寫的原子操作,封裝的必要性就會成為可選的問題從而引起不同的意見,不同的處理方式;這些處理方式的正確與否在抽象層面上難以界定,因而就需要根據所實施的環境和條件加以考量做出現實的判斷。關於作為資訊結構載體的Bean的成員是否應該直接暴露為公有變數還是應該透過一個方法來訪問的爭論,在抽象的層面上,與所謂暴露模型的問題一樣,都是關於封裝的爭論。然而,Bean的問題的具體條件和後果都與暴露模型有極大不同;如果不考慮Bean工具類的因素,前者基本上會侷限於程式碼風格這樣比較狹隘的範疇。暴露模型則不同,對封裝問題不同的處理所產生的設計後果的差異是非常巨大的,具體地說:過強的封裝會嚴重降低模型的通用價值,從而產生組合爆炸般的封裝程式碼。基於這一點,對於簡單的、基本是原子級的對模型的操作,直接深入模型的深層,理論上具有根本的合理性。直接透過物件導向操作語言操作模型,在相當多的情況下都是正確的選擇,它避免了大量的與數量極多並且變動不居的功能用例的平行的狹隘的結構元件的出現,使模型保持較高的抽象性、通用性、同一性。

模型的高階行為:組合邏輯
上一小節的分析實際上已經論證了組合邏輯作為模型的一個固有構成的必然性。這些邏輯如果由功能層基於領域靜態模型來實現;換句話說,由功能層直接操作靜態模型來實現組合邏輯,則會從實質上,而不僅僅是形式上違背封裝原則,其具體表現是在不合適的地方,比如JSP頁面或者Servlet中出現複雜的難於維護的QL語句;有時是較長的程式碼;使稀薄的控制層變厚重;這種現象也就是《POJO IN ACTION》中所描述的暴露模型的弱點(Also, the lack of a façade increases the chance that changes to the business tier could affect the presentation tier. There is also the risk of business logic creeping into the presentation tier.)。嚴格來說,這是教條主義的弱點,是對模型不分條件、不分部位、不加區分地暴露,是暴露過渡,是對封裝的反動過度,矯枉過正;是方法實施者、系統設計者本人把握能力的問題。這是方法論之所以不能夠代替設計者個人創造力、軟體開發之所以成為Art的根源。

不均勻暴露
以上兩個小節可以直接匯出一個結論:模型在各個部分的暴露與不暴露、暴露到什麼程度,是不均勻的,因為一個系統中不同的部分是否需要組合邏輯、邏輯組合的程度是不均勻的,正確地、辯證地處理這種不均勻性,自然會導致與之相適應的暴露程度。從這個意義上說其實也無所謂暴露模型或者封裝模型,因為我們在一個現實系統的開發中無法徹底擯棄或者實施任何一種方法,設計者所要做的無非是權衡、折中,在正確的時間、正確的地點作正確的事情。因此,從現在開始,當我們在積極的意義上來談論所謂暴露模型,所指的是這樣一個不均勻的暴露模型

暴露模型中功能用例有時直探模型的核心,有時訪問模型的表層,呈現出跨層訪問的結構特點。

另外幾個相關問題
領域實體及其關係透過QL語言暴露給功能層的前提是:這些實體及其關係形成了對概念模型的完備的再現;否則,如果實體集合需要經過複雜的裝配才能夠形成概念上的領域模型,則這種暴露就將導致功能層複雜的QL語句;這時,系統構造者面臨兩個選擇:或者調整實體物件及其關係使其足夠直觀地再現概念模型,或者透過封裝掩蓋一個不良的靜態模型。

適度封裝(或者暴露)的指導原則可以被推廣到其他方面,比如在處理應用邏輯與一個通用的、細粒度的API的關係上。但是,具體情況不同,在做法上差別極大,本文不作深入探討。



暴露模型與開發流程
最後我們略談一下暴露模型與開發流程方法論的關係。談到開發流程方法論,在這裡主要是指以重構為核心方法的敏捷開發和傳統的事前設計為重點的方法。首先一點是,暴露模型與兩類開發流程方法論之間沒有絕對的關係;其次,由上文所述能夠看出,暴露的不均勻性是一個需要極大創造性的指導原則,而不是設計教條,而一切創造性活動在本質上都更加傾向於一個進化的過程,因此,從這個意義上,暴露模型與敏捷開發、重構活動有天然的和諧關係;事實上,分佈於模型的各個部位上的不均勻程度與模型本身的其他方面一樣,伴隨著開發的歷史而形成自己變化發展的歷史。

[該貼被GUANPEI於2008-07-06 06:06修改過]

相關文章