OO系統設計師之路--分析模型系列(3)--分析模型的調整和優化[從老博客搬家至此]

這一篇拖了很長時間,除了懶之外,另一個主要原因是一直找不到思路。想歸納一下自己的設計經驗,找到一個相對容易學習的辦法,結果總是不得要領。終於不得不承認設計工作是一項創造性的工作,是沒有辦法用什麼固定的流程,普適的方法來完成的。除了知識和經驗之外,個人的悟性恐怕也是影響設計好壞的原因之一。這篇文章寫得很費勁,發現歸納出與具體需求無關的通用的一些方法真的很困難。相信對讀者來說這篇恐怕是到目前爲止最難懂的一篇了,因爲太多的東西是只可意會不可言傳的。如果讓讀者覺得困難了,只能說聲抱歉,我已經盡力了。市面上所有有關設計的書目,無非是講UML,講OO原則,講設計模式..這些要不就是理論,要不就是方法論,要不就是針對某一問題領域的解決方案。而當我試圖總結普適的實踐方法時,卻發現非常的困難。我盡力而爲,但仍免不了帶着個人色彩以及具體化。最後,只能希望通過講解一些關鍵點以及例子來給讀者提供一些思路,提供一些借鑑意義。至於一個通用的設計方法,我徹底放棄了,相信那是一個不可完成的任務。或者說以我目前的能力,還不足以總結出這樣的方法。

書歸正傳,這一篇講如何調整和優化上一篇的分析模型草圖。請注意我的用詞是調整和優化,也就是說,大部分工作都是基於已經完成的工作的。細心的讀者可能會發現,我一直試圖說明的是,需求,分析,設計這些工作並非那麼神祕,而是有一個程式化的過程。而我正希望整個過程越程式化越好,也希望讀者都能找到適合自己組織和項目類型的程式。軟件工程,既謂工程,必能遵循而重複。只有這樣才能降低成本,壓縮進度,減少溝通,提高質量。可重複的纔有意義。然而從現在開始,這個程式將不復存在,個人的作用開始登上舞臺了。

上一篇給出的草圖,基本上是不動腦子的。照搬了業務實體,每個實體前加了一個控制類,只用了一個界面,整個過程只是把用例場景又重新模擬了一遍。有的讀者要問,既然沒有任何的改變,又沒有分析的過程,那麼做這個工作不是白費力麼?實際上不是的,雖然是一個很簡單的草圖,但是我們已經完成了80%的工作,同時也爲後面的工作打下了非常好的基礎。這個草圖用最簡單最快速的方式把用例場景轉化成邏輯場景,代表了從需求到設計的演變過程。再接下來的設計工作,只要不丟掉這個草圖中的信息,不論怎麼設計都保證能夠滿足需求,將會省掉接下來大量的驗證工作而放心的在設計上下功夫。從效果上來說,草圖雖然不一定出現在最終的設計成果裏,但它的意義是顯而易見的。

有讀者對草圖中的控制類用法提出不同意見。爲什麼要一個實體類一個控制類呢?全部用一個控制類不好嗎?可以的。實際上在繪製草圖的時候可以參考本組織所採用的框架來決定控制類的用法。控制類的使用是最爲靈活的一個用法,但由於是草圖的關係,草圖的目的是用最快速最簡單的方法來把需求轉化到設計,再加上我個人覺得設計時由底向上比自頂向下要好(不容易遺露關鍵信息),也符合抽象是從特性向共性演變的特點,所以我個人習慣是先把控制類劃到最小,再透過框架來抽象,而不是一開始就考慮框架問題。

筆者剛纔說了,草圖代表了需求的實現,是一個細節的表露。接下來的優化的調整,就以此爲基礎。主要的輸入:草圖,系統架構,業務規則,補充用例規約,系統原型。主要的輸出:調整後的分析模型,子系統,組件視圖和部署視圖(針對分佈式應用而言)。

先說說分析模型的輸出

調整分析模型目的。設計是沒有標準答案的,這裏筆者只能試圖通過例子說明思路,不可能覆蓋所有問題,需要讀者自行體會了。或者提出問題,個別解答。調整分析模型的目的,是爲了使之具有更合理的結構,更有擴展能力和適應能力,能更清楚的表達邏輯。什麼樣的結構是好的?OO會說,封裝度高,耦合度低,接口(邊界)清楚...然而這些都是原則問題,筆者無法回答什麼是好的結構,因爲在筆者看來所有結構都有其優劣,就象經典的23個設計模式裏同時有該模式的優點與缺陷一樣。有趣的是,筆者發現能量守恆定律真的是普適真理,同樣適合軟件,封裝度越高,耦合度越低的代價通常是由結構的複雜度來替換程序的複雜度的。比如開發框架,例如Spring,其強大的擴展能力和極低的耦合度是由複雜的AOP和IOC模式爲代價的,其結果是完整的程序邏輯被分截成很多不連續的片段,對很熟悉AOP和IOC的程序員可能不是什麼問題,對經驗不多的,真是難以理解了。實際上,要做的事情不會因爲採用了某個結構而消失,只不過從程序中轉化到配置文檔或部署文檔而已。因此關於什麼是好的結構這個問題,請原諒筆者無法給出答案了,只有最適合的,沒有最好的。只想提醒一點,受能量守恆定律的制約,謹防過度設計,還是那句話,要做的事情不會因爲採用了某個結構而消失,它只是被轉化了。因此請根據業務規則,補充規約中的要求,參考項目週期,成本,開發人員水平等等因素,評估結構調整的得失,得出最平衡的方案。

劃分子系統。在本BLOG中曾經與網友rwyx討論過子系統劃分的問題,詳細內容可以去看以武會友欄目《系統分析,業務建模,UML,RUP相關》中關於UC矩陣的討論,由於內容比較多,這裏只例舉筆者的觀點和方法:我不認爲子系統應該是功能性的,這是UC關注的點,我認爲是內在邏輯性的,所以只有在內部邏輯得以明確,也就是分析模型出來之後,纔可能決定子系統。劃分子系統依據於分析模型的結果。我的做法是先把分析模型做出來,然後嘗試將分析模型中的對象放入不同的包(這裏的確有經驗的成份,並不是一個個瞎試的,最初的依據還是來自業務用例,把一個業務用例當成一個包,在此基礎上再改進)。這時會發現一些有趣的內容,比如,某個control類有好幾個包都需要,比如,某個包中的某個Entity類被多達七八個其它包所引用,比如,某個bandage類要與分散在七八個包裏的control類打交道...爲了解決這些問題,嘗試將分析類移到別的包,合併一些包,分揀出公有元素形成新包,也就是所謂的LIB等等。最理想的情況,那些分析類的所有依賴都在侷限一個包裏,或只與LIB有關,或僅通過一個bandage與其它包交互....到這時就形成了子系統的雛形了,剩下的工作,就是參考UI的要求,決定將哪些包合成一個更高層次的包,這個包包含了UI要求,由於基礎來源於業務用例,基本上也會符合業務習慣要求,這個包就是子系統,取個合適的名字就OK了。
總結一下,大部分子系統劃分是自頂向下的方法,我用的是自底向上的方法。如果構成底部組件級別的包已經耦合度很低了,再用它們來組合子系統就自由得多,儘量參考UI要求就是了,這是爲什麼在草圖中我把控制類分得很細的原因。不過得提醒讀者,通過分析模型劃分子系統的方法是筆者自己獨創的,尚未有其它文獻資料的支持,僅供參考,慎用^_^

組件視圖。將聯繫緊密,共同向外提供某種服務的分析類組合起來,形成一個組件。這個組件將有可能是被複用的。但組件視圖不一定是需要提取的,筆者一般使用組件視圖情形是在分佈式,或與外部系統有交互的情況下才做。筆者對組件視圖的使用是基於SOA思想的,一個組件就是一個WebService模塊,這個模塊有被複用的要求,有被獨立部署的要求,如果沒有這樣的業務需求,就係統內部而言,筆者認爲並無組件視圖的必要,包圖就足夠了。並且Rose裏的組件視圖實在是...難用。那組件是如何形成的呢?筆者做組件是通過觀察邊界類而來,並且這個邊界的兩邊都是系統(不同於界面有一邊是人)。觀察這個邊界兩邊系統的交互情況,如果交互很頻繁,並且涉及雙方的多個對象,這時就要考慮組件了。用一個邏輯的組件名字,將內部被影響到的對象組合起來,透過這個組件來與對方系統交互。同時維護交互目的的單純性(比如不要把取錢和開戶放在一個組件裏,這是兩個不同的目的),一類目的一個組件。如果是分佈式系統,還得考慮組件涉及到的對象可以被獨立部署問題。提醒讀者注意,筆者對組件視圖的使用方式和理解也與一般UML教科書不同,目前也未有其它文獻支持,僅供參考

部署視圖部署視圖劃分出系統的網絡拓撲節點情況。不過老實說我覺得Rose中這個視圖不是太有效的。寧願選擇Visio來繪製節點圖。部署視圖筆者不多說,因爲真正需要做部署視圖的一般是分佈式應用,一般也都需要企業級應用服務器支持,如Weblogic,Webshpere等,購買了這些產品的項目,自然會同時有擁有這些大公司的技術支持,直接請他們提供解決方案好了。

接下說說調整分析模型的關鍵點

以上是分析模型在調整過程中可能需要產出的一些內容。在這之前的過程都是程式化的,而今天的內容,則需要個人的經驗和能力了。下面筆者儘量說明一些調整的關鍵點。

關鍵點之一:業務規則,尤其是來自補充用例規約中的全局規則 
業務規則需要被評估,它們是普遍存在的?還是局部存在的?所謂普遍,是指這個規則在大多數情況下都會起作用。所謂局部,是指這個規則只在某種情形下才起作用。對於普遍的規則,需要在分析模型甚至架構上處理,而局部規則可以由後續的設計模型處理。普遍規則的例子:actor所有操作都應該被記錄;actor存取資源時應當被授權;局部規則的例子:actor在下一次借書前沒有逾期未歸還的書,否則不能借閱。前兩個普遍規則例子將反應到本篇的分析模型圖裏。後一個局部規則例子要到設計模型時再給出示例圖。 
也應當關注那些複雜的,可能將來會經常變化的那些規則。如果這種變化的可能是普遍存在的,應當在分析模型中給予關注,否則,可由設計模型來處理。例如,不論是借書的條件,可供查詢圖書的條件,借閱證有效條件....都是很有可能變化的,那麼,可能需要在草圖的邊界類和控制類之間加入一個Factory,來保證一定的規則替換能力。但如果只有借書條件可能變化,這個Factory只需要加在借書控制器上,由設計模型處理就行了。

關鍵點之二:結構化和耦合度調整 
不好的結構是網狀結構,對象之間互相依賴。這樣的結構藕合度高,擴展能力和適應性就差,改動程序時經常牽一髮而動全身。例如草圖中的圖書、借閱證、借書藍和借閱定單。好的結構是樹狀結構,對象之間的依賴是單向的,不交叉的。調整後的分析類圖表示了這一轉變。當然有時候並不是能夠完全做到這一點,儘量做到,並防止過度設計。

關鍵點之三:交互集中點調整 
若某一個對象的交互非常多,它與很多個對象都在交互,這個對象就是問題多發地帶了!也就是所謂的critical chain,瓶頸...它應當被調整。由於筆者所用的這個例子較爲簡單,爲了延續一直以來的示例,唯一可以被看作是Critical chain的就是界面了,雖然用界面來講這個例子不太合適,但思路是可以借鑑的。調整交互集中問題的方法有,重新規劃職責或增加冗餘,或增加中間調合層等等....這個結果可參看後面的分析模型圖。

接下來,是根據上面的講述產筆者提供的一些例子。這些例子只可意會不可言傳的,很難說明,能否理解就看讀者個人在OO設計上的經驗了。

分析模型原圖: 

 

針對業務規則:actor所有操作都應該被記錄,分析模型所建立的一個解決方案。但絕不僅這一個方案。

類圖:

交互圖:

 

針對業務規則:actor存取資源時應當被授權,分析模型所建立的一個解決方案,但絕不僅這一個方案。

類圖:

交互圖:

 

調整耦合度,分析模型重新調整後的結構,但絕不僅這一個方案。

類圖:

交互圖:

 

交互集中點調整,分析模型所建立的三個方案。由於筆者的案例簡單,以前的例子中未出現交互集中點,因此用界面作爲例子來講。讀者應當把這個例子中的界面設想爲一個Control類或是一個Entity類會更加合理。不過思路是相通的。當然解決方案絕不僅止這三種 
方案一:重新規劃職責 

方案二:增加冗餘 

方案三:增加中間調合層 

一個組件圖的例子,網上交費業務的組件視圖 

再次提醒讀者,這些例子只是針對某個問題的解決方案之一,不可避免的帶着筆者的個人經驗色彩。這些解決方案不是真理,沒有高下,甚至沒有對錯。目的只是爲了提供思路,而非模板和教條。熟悉設計模式的讀者可以從設計模式中找到很多解決這類問題的模式。讀者不應該拘泥於研究筆者這些解決方案,這些方案僅是爲了配合說明調整分析模型關鍵點而提供的示例而已,重要的是理解那幾個關鍵點。

這一篇當中,筆者講述了一些調整分析模型的要點,並舉了幾個例子。筆者不得不說的是,寫這篇文章真的花費不少力氣。設計是一種創造性工作,隨環境而變,隨要求而變,隨設計師而變...要總結出一套方法來實在是困難。筆者只能就自己的經驗寫一些要點。誠然,這些例子不足以解決所有問題。目前估計沒人能做到"統一設計方法",真到了那一天,軟件就是工業化生產了。筆者希望通過這幾個要點和例子,能夠激發讀者的思路,舉一反三,而不是照葫蘆畫瓢(我相信想畫也畫不出來)。今天這篇同時也揭示了分析模型到底要做些什麼。讀者也可以體會一下,調整分析模型與原來沒有分析模型時調整設計類相比哪個更容易些,工作量更小些。

接下來,要討論如何轉化到設計類的問題了。但是設計類是實現類,它必然與軟件框架,系統架構,實現語言息息相關。所以下一篇將討論軟件框架和系統架構在UML裏的表現方形式,再下一篇才討論分析類到設計類的轉化問題。敬請期待。

 

*********************************************************

作者coffeewoo 歡迎您訪問文章原始出處 : http://blog.csdn.net/coffeewoo,閱讀中有任何問題可以在BLOG上留言或發郵件到 coffeewoo@gmail.com,我將盡力爲您解答。具有代表性的問題我會以 Q &A的形式收錄到對應的文章之後。希望本系列文章對您有幫助。歡迎轉載,敬請註明,謝謝 ^_^

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