[toc] 領域驅動設計 運用領域模型 綁定模型和實現 聰明的項目組成員花費了幾個月的時間進行仔細的研究並且開發出了詳盡的領域模型(類圖)。然而對類圖研究不能讓我深入地瞭解該應用程式的代碼和設計,這讓我備感困擾。當開發人員開始實現應用程式時,他們很快就發現,儘管分析人員說得頭頭是道,他們依然無法將這 ...
目錄
領域驅動設計-運用領域模型-綁定模型和實現
聰明的項目組成員花費了幾個月的時間進行仔細的研究並且開發出了詳盡的領域模型(類圖)。然而對類圖研究不能讓我深入地瞭解該應用程式的代碼和設計,這讓我備感困擾。當開發人員開始實現應用程式時,他們很快就發現,儘管分析人員說得頭頭是道,他們依然無法將這種錯綜複雜的關係轉換成可存儲、可檢索的且具有事務完整性的單元。
由於模型是“正確的”,這是經過技術分析人員和業務專家大量協作才得到的結果,因此開發人員得出這樣的結論:無法把基於概念的對象作為設計的基礎。於是他們開始進行專門針對程式開發的設計。他們的設計確實用了一些原有模型中類和屬性的名稱進行數據存儲,但這種設計並不是建立在任何已有模型的基礎上的。
這個項目雖然建立了領域模型,但是如果模型不能直接幫助開發可運行的軟體,那麼這種紙上談兵的模型又有什麼意義呢?
領域驅動設計要求模型不僅能夠指導早期的分析工作,還應該成為設計的基礎。這種設計方法對於代碼的編寫有著重要的意義。不太明顯的一點就是:領域驅動設計要求一種不同的建模方法
個人理解:建了模型可以更快瞭解所需知識,可又不能轉化成程式代碼實現,到底要怎樣?我也搞不懂了,反正覺得好複雜
MODEL-DRIVEN DESIGN
嚴格按照基礎模型來編寫代碼,能夠使代碼更好地表達設計含義,並且使模型與實際的系統相契合。
那些壓根兒就沒有領域模型的項目,僅僅通過編寫代碼來實現一個又一個的功能,它們無法利用前兩章所討論的知識消化和溝通所帶來的好處。如果涉及複雜的領域就會使項目舉步維艱。
另一方面,許多複雜項目確實在嘗試使用某種形式的領域模型,但是並沒有把代碼的編寫與模型緊密聯繫起來。這些項目所設計的模型,在項目初期還可能用來做一些探索工作,但是隨著項目的進展,這些模型與項目漸行漸遠,甚至還會起誤導作用。所有在模型上花費的精力都無法保證程式設計的正確性,因為模型和設計是不同的。
模型和程式設計之間的聯繫可能在很多情況下被破壞,但是二者的這種分離往往是有意而為之的。很多設計方法都提倡使用完全脫離於程式設計的分析模型,並且通常這二者是由不同的人員開發的。之所以稱其為分析模型,是因為它是對業務領域進行分析的結果,它在組織業務領域中的概念時,完全不去考慮自己在軟體系統中將會起到的作用。分析模型僅僅是理解工具,人們認為把它與程式實現聯繫在一起無異於攪渾一池清水。隨後的程式設計與分析模型之間可能僅僅保持一種鬆散的對應關係。在創建分析模型時並沒有考慮程式設計的問題,因此分析模型很有可能無法滿足程式設計的需求。
這種分析中會有一些知識消化的過程,但是在編碼開始後,如果開發人員不得不重新對設計進行抽象,那麼大部分的領域知識就會被丟棄。如此一來,就不能保證在新的程式設計中還能保留或者重現分析人員所獲得的並且嵌入在模型中的領域知識。到了這一步,要維護程式設計和鬆散連接的模型之間的對應關係就很不合算了。
個人理解:業務畫的模型圖,在技術人員看來,需要進行翻譯成程式模型圖(流程圖),這樣,兩個模型之間肯定會有不同的部分,會有一些領域知識捨棄,那這兩個模型對應關係需要來維護,無疑增加了複雜度。
無論是什麼原因,軟體的設計如果缺乏概念,那麼軟體充其量不過是一種機械化的產品——只實現有用的功能卻無法解釋操作的原因。
如果整個程式設計或者其核心部分沒有與領域模型相對應,那麼這個模型就是沒有價值的,軟體的正確性也值得懷疑。同時,模型和設計功能之間過於複雜的對應關係也是難於理解的,在實際項目中,當設計改變時也無法維護這種關係。若分析與和設計之間產生嚴重分歧,那麼在分析和設計活動中所獲得的知識就無法彼此共用。
個人理解:上面的我也沒看懂,反正就是說業務涉及的模型和技術流程圖是有很大不同,原因是思考方式不同,這樣很難對應維護。
MODEL-DRIVEN DESIGN(模型驅動設計)不再將分析模型和程式設計分離開,而是尋求一種能夠滿足這兩方面需求的單一模型。不考慮純粹的技術問題,程式設計中的每個對象都反映了模型中所描述的相應概念。這就要求我們以更高的標準來選擇模型,因為它必須同時滿足兩種完全不同的目標。
有很多方法可以對領域進行抽象,也有很多種設計可以解決應用程式的問題。因此,綁定模型和程式設計是切實可行的。但是這種綁定不能夠因為技術考慮而削弱分析的功能,我們也不能接受那些只反映了領域概念卻捨棄了軟體設計原則的拙劣設計。模型和設計的綁定需要的是在分析和程式設計階段都能發揮良好作用的模型。如果模型對於程式的實現來說顯得不太實用時,我們必須重新設計它。而如果模型無法忠實地描述領域的關鍵概念,也必須重新設計它。這樣,建模和程式設計就結合為一個統一的迭代開發過程。
將領域模型和程式設計緊密聯繫在一起絕對是必要的,這也使得在眾多可選模型中選擇最適用的模型時,又多了一條選擇標準。它要求我們認真思考,並且通常會經過多次反覆修改和重新構建的過程,但是通過這樣的過程可以得到與設計關聯的模型。
要想創建出能夠抓住主要問題並且幫助程式設計的單一模型並沒有說的那麼容易。我們不可能隨手抓個模型就把它轉化成可使用的設計。只有經過精心設計的模型才能促成切實可行的實現。
個人理解:建模好難,不管怎麼說,將業務和技術思維抽象成通用模型,本身就是學習成本,不是人人都能達到的。真的懷疑做模型的時間是不是還不如直接開發來的乾脆,少搞這些虛頭巴腦的東西。老外對模型是真愛!
建模範式和工具支持
為了使MODEL-DRIVEN DESIGN發揮作用,一定要在可控範圍內嚴格保證模型與設計之間的一致性。要實現這種嚴格的一致性,必須要運用由軟體工具支持的建模範式,它可以在程式中直接創建模型中的對應概念。
面向對象編程之所以功能強大,是因為它基於建模範式,並且為模型構造提供了實現方式。從程式員的角度來看,對象真實存在於記憶體中,它們與其他對象相互聯繫,它們被組織成類,並且通過消息傳遞來完成相應的行為。許多開發人員只是得益於對象的技術能力——用其組織程式代碼,只有用代碼表達模型概念時,對象設計的真正突破之處才彰顯出來。Java和許多其他工具都允許創建直接反映概念對象模型的對象和關係。
沒看懂,直接忽略。設計不是一蹴而就的。我們需要反覆研究領域知識,不斷重構模型,才能將領域中重要的概念提煉成簡單而清晰的模型。
為什麼模型對用戶至關重要
從理論上講,也許你可以向用戶展示任何一種系統視圖,而不管底層如何實現。但實際上,系統上下層結構的不匹配輕則導致誤解,重則產生bug。
如果程式設計基於一個能夠反映出用戶和領域專家所關心的基本問題的模型,那麼與其他設計方式相比,這種設計可以將其主旨更明確地展示給用戶。讓用戶瞭解模型,將使他們有更多機會挖掘軟體的潛能,也能使軟體的行為合乎情理、前後一致。
個人理解:這裡說了很多理論,其實就是一點,如果模型做的不好,直接導致做出來的東西會複雜難用,用戶難以接受。
HANDS-ON MODELER
人們總是把軟體開發比喻成製造業。這個比喻的一個推論是:經驗豐富的工程師做設計工作,而技能水平較低的勞動力負責組裝產品。這種做法使許多項目陷入困境,原因很簡單——軟體開發就是設計。雖然開發團隊中的每個成員都有自己的職責,但是將分析、建模、設計和編程工作過度分離會對MODEL-DRIVEN DESIGN產生不良影響。我曾經在一個項目中負責協調不同的應用程式開發團隊,幫助開發可以驅動程式設計的領域模型。但是管理層認為建模人員就應該只負責建模工作,編寫代碼就是在浪費這種技能,於是他們不准我編寫代碼或者與程式員討論細節問題。
個人理解:現在軟體工程就是分了很多流程:調研-需求評審-概要設計-詳細設計-系統開發-測試-上線-維護,難道每個人負責自己的模塊不好嗎?很多對日外包就是拿日本人設計好的偽代碼和流程圖,直接用程式翻譯出來。難道自己的理解有問題了?
開始項目進展的還算順利。我和領域專家以及各團隊的開發負責人共同工作,消化領域知識並提煉出了一個不錯的核心模型。但是該模型卻從來沒有派上用場,原因有兩個。
其一,模型的一些意圖在其傳遞過程中丟失了。模型的整體效果受細節的影響很大這些細節問題並不是總能在UML圖或者一般討論中遇到的。如果我能擼起袖子,直接與開發人員共同工作,提供一些參考代碼和近距離的技術支持,那麼他們也許能夠理解模型中的抽象概念並據此進行開發。
第二個原因是模型與程式實現及技術互相影響,而我無法直接獲得這種反饋。例如,程式實現過程中發現模型的某部分在我們的技術平臺上的工作效率極低,但是經過幾個月的時間,我才一點一點獲得了關於這個問題的全部信息。其實只需較少的改動就能解決這個問題,但是幾個月過去了,改不改已經不重要了。因為開發人員已經自行編寫出了可以運行的軟體——完全脫離了模型的設計,在那些還在使用模型的地方,也僅僅是把它當作純粹的數據結構。開發人員不分好壞地把模型全盤否定,但是他們又有什麼辦法呢?他們再也不願意冒險任由呆在象牙塔里的架構師擺佈了。
與其他項目一樣,這個項目的初始環境傾向於不讓建模人員參與太多的程式實現。對於該項目所使用的大部分技術,我都有著大量的實踐經驗。在做建模工作之前,我甚至曾經在同類項目中領導過一個小的開發團隊,所以我對項目開發過程和編程環境非常熟悉。但是如果不讓建模人員參與程式實現,我就是有這些經歷也無法有效地工作。
如果編寫代碼的人員認為自己沒必要對模型負責,或者不知道如何讓模型為應用程式服務,那麼這個模型就和程式沒有任何關聯。如果開發人員沒有意識到改變代碼就意味著改變模型,那麼他們對程式的重構不但不會增強模型的作用,反而還會削弱它的效果。同樣,如果建模人員不參與到程式實現的過程中,那麼對程式實現的約束就沒有切身的感受,即使有,也會很快忘記。MODEL-DRIVEN DESIGN的兩個基本要素(即模型要支持有效的實現並抽象出關鍵的領域知識)已經失去了一個,最終模型將變得不再實用。最後一點,如果分工阻斷了設計人員與開發人員之間的協作,使他們無法轉達實現MODEL-DRIVEN DESIGN的種種細節,那麼經驗豐富的設計人員則不能將自己的知識和技術傳遞給開發人員。
HANDS-ON MODELER(親身實踐的建模者)並不意味著團隊成員不能有自己的專業角色。包括極限編程在內的每一種敏捷過程都會給團隊成員分配角色,其他非正式的專業角色也會自然而然地產生。但是如果把MODEL-DRIVEN DESIGN中密切相關的建模和實現這兩個過程分離開,則會產生問題。
整體設計的有效性有幾個非常敏感的影響因素——那就是細粒度的設計和實現決策的質量和一致性。在MODEL-DRIVEN DESIGN中,代碼是模型的表達,改變某段代碼就改變了相應的模型。程式員就是建模人員,無論他們是否喜歡。所以在開始項目時,應該讓程式員完成出色的建模工作。
任何參與建模的技術人員,不管在項目中的主要職責是什麼,都必須花時間瞭解代碼。任何負責修改代碼的人員則必須學會用代碼來表達模型。每一個開發人員都必須不同程度地參與模型討論並且與領域專家保持聯繫。參與不同工作的人都必須有意識地通過UBIQUITOUS LANGUAGE與接觸代碼的人及時交換關於模型的想法。
將建模和編程過程完全分離是行不通的,然而大型項目依然需要技術負責人來協調高層次的設計和建模,並幫助做出最困難或最關鍵的決策。
個人理解:每個人都要會一點建模,就算是開發人員,也要參與其中,就算是業務人員,也要稍微懂些代碼。每個人要有自己的專業能力,同時也要全面發展,瞭解整個流程的工作內容。一句話:可以不做,但是不能不會。突然有一個需要程式員去做需求或者詳細設計,也要能扛下來這個任務。目的不是讓一個人做多個任務,擔任軟體開發流程中的多個職責,而是懂得一些後大家溝通建模沒有障礙,會相互理解。