http://yvesgao.blogchina.com/2844723.html
摘要:
本文是我的數據庫管理系統課程設計的作業。本文以該系統的需求、分析&設計和實現為主線,記錄了在開發過程中我使用的方法,遇到的問題以及一些心得。應該說這是我目今程序設計思想的總結。另外,本文也闡述了我所認為的個人軟件開發的一般過程。
寫在正文前面:
編程序也有些許時日了,覺得最明顯的長進就是雙手十指變得靈活非常,打字很快了還練就了盲打,可漸漸的手太快腦子卻跟不上趟了。論語說,學而不思則怠,確實是有些怠了。
我不想只做coder。
后來接觸并了解了一些面向對象的思想,越來越欣喜,因為眼前豁然開朗,發覺開始遠離coder了。
正文:
一、 需求
1、 如何開始
Grady Booch說,如果你面對一個問題,不知道如何入手,就從你確實能夠理解的地方入手。
這個所謂“確實能夠理解的地方”到底在哪呢?很明顯用戶需求是這樣一個地方,原因很簡單,作為用戶使用軟件當然要比開發這個軟件容易的多。這也是目標導向方法所倡導的,因為最終用戶是軟件的真正驗收者,只有他們有決定權,好與不好全憑他們的好惡,仍是那句話,用戶是上帝。
MiniDatabase的需求不用我太費心,因為已經寫到了課程設計指導書上,這里我的老師就是上帝了:)。
如下的幾點需求值得慶幸——因為少,但要想繼續進行開發就要更深入的分析。
2、 用例分析
無疑,用例分析是一個優秀的深入分析的方法,它仍然是目標導向的,但更細致不僅是羅列功能的描述而是功能實現后用戶看到的和一些必要但看不到的軟件行為。我認為一份優秀的深入的用例分析可以整理成一份軟件的使用手冊。
聽上去很“神奇”,軟件還沒開發出來——實際上一行代碼還未寫過,使用手冊就可以預先寫成,似乎本末倒置。
這其實來源于一種認識,設想如果我們的上帝具有與我們同等的技術力,那么他一定能開發出自己滿意的產品。那么要上帝學習我們的技術么?顯然,這太難了,還是讓我們學習上帝的賞析理念和好惡準則吧——我們得扮演上帝,相比之下,這會簡單些。
對于將要建成的系統來講,用例是接口,是表層的系統行為,一定得把握住這一點,在這個階段我們只思考表層的系統行為,我們得集中精力一步步把事情做好。
用例還有兩個好處就是文檔化和標準化
文檔化的用例可以糾正我們在實際和實現階段出現的偏離軌道的行為,你得時刻拿它出來和現行的工作對照,千萬不能出現偏差,用例其實就是“圣經”,因為它記錄了上帝的要求。
標準化的用例用于交流和比較,用例展現了統一的風格,比如完成相似工作的用例應該有相似的工作流。
凡此種種,用例為綱,綱舉目張。
MiniDatabase的用例較為簡單但挺長的,為了行文的流暢,我把它放到附錄里了。
二、 分析&設計——在題域與解域邊緣
1、 如何開始
用例只能幫助我們從“上帝”的角度認知應用系統,但說實話,這樣不能為我們的系統添上哪怕一磚一瓦,我們要想繼續開展工作,還得做些銜接性的活計。
上一個階段,我們所做的需求分析工作,其實是劃定了一個“上帝”所處的領域,至少是和我們系統相關的領域。
在需求分析的文檔理一定充斥著大量同樣或相近的詞匯(這要求我們用詞得規范些),我們得總結這些相同、相近的詞匯,這些詞有的代表某個動作、某個物件或聯系等,其實這些詞足以代表領域的系統范圍。
我們需要對這個系統建模,得打起十二分精神,這就好像萬丈高樓的設計圖,平地起就靠它了。
前面分析出的許多詞匯,我將其統稱為概念。
我認為,建模的實質無非是以解域工具描述題域概念進而解決問題的方法。
領域建模主要就是針對這些概念進行建模,概念本屬題域,與解域有頗多隔膜,將其轉換至解域則頗費周章,所以拉近解域與題域則是建模方法的研究方向。
面向對象的方法便占此擅場,正如Bruce Eckle 所說,“”雖然有些夸張但確是精要所在。
MiniDatabase即是以oo的思想指導完成的,下面我就詳述這一過程。
2、 題域建模
2.1理析概念
我認為對概念建模是獲得良好設計的敲門磚,并且將會貫穿整個設計階段,當陷入迷茫時深入理解“概念”將使你重回正道。
我們這個MiniDatabase里有這樣一些概念:MiniDatabase是一個數據庫管理系統,數據庫包含多個數據表和查詢,每個數據表和查詢包含唯一一個表模式和多條記錄,每條記錄有多個單元,每個單元又有……
上面這段話是對需求分析的一個提煉,這是從題域向解域邁出的第一步,幾個概念已經很清晰了:數據庫,數據表,查詢,表模式,記錄,單元……
對應于面向對象的思想,這些就是對象,例如:數據庫對象即是題域概念數據庫的解域描述,你能發現用面向對象的方法,題域中有什么就可以拿到解域中把它作為對象,一切都那么自然。
對象之間的關系也是一種,也需要被建模,如:數據庫包含數據表和查詢,這句話中就有兩個關系——包含和關聯。
通常不能希冀一次就歸納出所有的概念,很顯然這不符合人們認知事物循序漸進的規律,例如,在實現階段發現了新的概念你仍然可以回過頭來修改設計——這也就是所謂的迭代。
有些專家和書籍還是推薦將分析和設計做得盡可能的細致以避免反工,理論上確是應花費大量的時間進行分析和設計,不過這些畢竟是抽象的,通常得有積年累月的開發經驗;還有的方法傾向于短期的迭代,這相當于不停的測試,有時這很浪費時間,畢竟,在一定范圍內大腦的抽象能力還是搞得定的。
所以還是隨心所欲吧感覺找不到概念時就像下進行吧。
2.2對象的職責和狀態
對題域概念的解域建模并不僅停留在理析概念的階段,更深入的我們得認知對象的行為和狀態。
2.2.1什么是對象的職責?
這個問題看似簡單。比如在 MiniDatabase 中,我想創建一個數據表,這是誰的職責呢?是數據表自身么?顯然不是,這不符合邏輯,那么一定是數據表的擁有者——數據庫,似乎合理,但更合邏輯的,該職責應歸附MiniDatabase管理器,由管理器搜集相關信息,創建一個數據表,然后傳遞給數據表的擁有者,并由其保存和維護,所以數據庫的職責是管理和組織而不是創建(其實這個例子說明了一個常見的設計,即創建和維護的解耦,后面還會提到)。
對象的職責有大有小,有表有里,一個大的或表層的職責可能有幾個小的里層的職責完成,將大的分割成幾個小的是一個很常用的方法(這是由人認知的局限性造成的)。
一個對象的職責也可能委托給其他的對象。
對于對象職責的劃分似乎沒有一定之規,也沒有好壞之分,只有合適與不適之分,所謂合適與不適往往又要通過后續的工作來檢驗,所以這又是依靠經驗才能做好的事情,但我感覺很多時候只要把握住題域概念,思考其在題域中的職責,理清其中的邏輯關系,對應過來還是能得到一個較為合適的職責劃分的。
2.2.2什么是對象的狀態
對象通過狀態區別自己和其他對象,比如一個數據庫包含多個數據表,如何區別這些表呢?可以通過表名字,這名字就是表的狀態了。
一般狀態是和職責關聯的,一些狀態可能決定了職責,一些職責可能啟發出某些狀態。
狀態的分析比職責更隱晦,因為大多數情況下,職責是表現于對象之外的,而狀態則內儲于對象之中。
2.3將對象變成類
從特殊到一般是認知的普遍規律之一,從對象到類就遵循了這一規律。
為什么要將對象變成類?
將對象變成類是又一次抽象,是一次歸納和整理,得確信題域中是有某種規律或定式的,認知這些能讓我們從全局來把握題域,好處之一就是應付題域的變化——所謂萬變不離其宗,握其宗本則為執牛耳者了。
依憑對對象的認識——職責和狀態,我們對其分門別類,劃歸類似的職責和狀態而成一類,幾小類又合并成一大類,由此可建立一個類的體系。如圖:
在MiniDatabase中,數據表和查詢是一類,因為查詢是一個有條件的數據表。數據庫和數據標也是一類,因為他們都包含其它的對象,如此等等……
劃歸一類的原因可能很明顯(如查詢和數據表),也可能很抽象(如數據庫和數據表),一般越向類體系上溯,其分類原則越抽象,但必須合乎概念和邏輯,類的劃分也應是以概念為準繩的。
我仍想強調,要構造優秀的類體系圖,請緊緊把握題域概念。如果確實做到了這一點,不妨稱此為概念類,對象則為概念對象。
3、 解域建模
進入解域之前,你得確信題域的工作已經差不多了,一個檢驗的辦法是:看看是不是所有的概念已經出現在類體系圖中了。千萬不要太倉促,急于求成只能使你陷入兩難境地——推翻設計但又缺少時間,還是草草了事而容忍一堆難于維護的代碼。
這一節我將更加貼近MiniDatabase,具體說說MiniDatabase是如何架構的。
3.1設計模式
對于新手來說,題域建模比解域建模容易,但對于那些經驗豐富的人,更令其頭疼的卻是題域,他們可能會被用戶一天一變的需求搞的焦頭爛額,但在解域卻游刃有余。
為什么呢?
因為,解域里存在大量的定式,更專業一點叫模式,解域里的定式一部分被稱為設計模式。
至于何時向模型引入模式,我想可以從兩個方面思考,一是為了向系統提供某種特性——通常是靈活性;二是憑經驗對某些典型問題應用模式會帶來好處。
3.1.1Composite模式
Composite模式用來表示對象的部分——整體層次結構。一般來講,似乎稍具規模的應用都應該有所謂“對象的部分——整體層次結構”,所以上來先試試Composite模式會使解域建模的突破口。
這種有多個抽象層次的模式主要目的就是為其繼承層提供統一的訪問接口,從概念上講就是抽象、泛化,抽象層次多了就可以將不同的接口放到不同的層次上,這樣就對接口進行了歸類,比如下圖:
在圖中,對于Database,它既需要Add、Delete……接口來管理其子對象,又需要Save,Load接口來保存自己,但你不能將這些接口放到同一個抽象層上——比如CdataCollection,顯然CDataLeaf沒有子對象,也就沒有Add、Delete接口。
剛才提到了支持對象管理的Add、Delete接口,這些接口的實現仍是委托給一個已有的容器型對象。
在我看來Composite模式的另一個重要之處就是把題域模型與解域模型聯合起來。
4、 小結
前面花了大量篇幅講述了如何進行題域建模和解域建模,我想應該感到,由于面向對象方法的引入使題域和解域的界限漸漸模糊,比如對象和類出現在題域也在解域發揮重要作用。
實際上任何建模的方法都致力于拉近題域與解域,面向對象的方法正占此擅場。應該說,面向對象的思想結合UML的表達力,就可以貫通題域與解域了。
正如本章標題所寫:“分析&設計——在題域與解域邊緣”
分析和設計同屬“從題域過渡到解域的階段”,有些書籍傾向于將分析和設計隔離開,我認為分析和設計同在題域與解域的邊緣,他們交織在一起,很難說分析只針對題域,設計只針對解域,只能說分析注重題域,設計注重解域,而其中的聯系——即如何平滑的從題域過渡到解域卻是重中之重,由此將其分門別類的隔離開卻是過于武斷了,所以文中之用題域建模和解域建模來類比的描述這兩個概念。
題域與解域的交疊確實常常困擾我,比如,在分析時我常常發現自己在考慮是否使用一個Observe模式,抑或是在設計時發現某個概念類應繼承在另一個之下,一段時間的焦灼讓我豁然,我想也不必拘泥于分清分析和設計階段,超前進行設計,回頭返工分析都是自然的,前者能幫助平滑過渡,后者則避免一些重構。
分析和設計的工作實在很大(有所謂70%/30%理論,即70%的時間花在前期的需求、分析和設計,30%則花在后期的實現、測試和布置),前面之敘述了主體部分,后面一小節說些我的點滴心得,徒做拾遺。