版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
第11章面向?qū)ο笤O計11.1面向?qū)ο笤O計的準則11.2啟發(fā)規(guī)則11.3軟件重用11.4系統(tǒng)分解11.5設計問題域子系統(tǒng)11.6設計人機交互子系統(tǒng)11.7設計任務管理子系統(tǒng)11.8設計數(shù)據(jù)管理子系統(tǒng)11.9設計類中的服務11.10設計關聯(lián)11.11設計優(yōu)化11.12小結習題如前所述,分析是提取和整理用戶需求,并建立問題域精確模型的過程。設計則是把分析階段得到的需求轉(zhuǎn)變成符合成本和質(zhì)量要求的、抽象的系統(tǒng)實現(xiàn)方案的過程。從面向?qū)ο蠓治龅矫嫦驅(qū)ο笤O計(OOD),是一個逐漸擴充模型的過程?;蛘哒f,面向?qū)ο笤O計就是用面向?qū)ο笥^點建立求解域模型的過程。盡管分析和設計的定義有明顯區(qū)別,但是在實際的軟件開發(fā)過程中二者的界限是模糊的。許多分析結果可以直接映射成設計結果,而在設計過程中又往往會加深和補充對系統(tǒng)需求的理解,從而進一步完善分析結果。因此,分析和設計活動是一個多次反復迭代的過程。面向?qū)ο蠓椒▽W在概念和表示方法上的一致性,保證了在各項開發(fā)活動之間的平滑(無縫)過渡,領域?qū)<液烷_發(fā)人員能夠比較容易地跟蹤整個系統(tǒng)開發(fā)過程,這是面向?qū)ο蠓椒ㄅc傳統(tǒng)方法比較起來所具有的一大優(yōu)勢。生命周期方法學把設計進一步劃分成總體設計和詳細設計兩個階段,類似地,也可以把面向?qū)ο笤O計再細分為系統(tǒng)設計和對象設計。系統(tǒng)設計確定實現(xiàn)系統(tǒng)的策略和目標系統(tǒng)的高層結構。對象設計確定解空間中的類、關聯(lián)、接口形式及實現(xiàn)服務的算法。系統(tǒng)設計與對象設計之間的界限,比分析與設計之間的界限更模糊,本書不再對它們加以區(qū)分。本章首先講述為獲得優(yōu)秀設計結果應該遵循的準則,然后具體講述面向?qū)ο笤O計的任務和方法。所謂優(yōu)秀設計,就是權衡了各種因素,從而使得系統(tǒng)在其整個生命周期中的總開銷最小的設計。對大多數(shù)軟件系統(tǒng)而言,60%以上的軟件費用都用于軟件維護,因此,優(yōu)秀軟件設計的一個主要特點就是容易維護。本書第5章曾經(jīng)講述了指導軟件設計的幾條基本原理,這些原理在進行面向?qū)ο笤O計時仍然成立,但是增加了一些與面向?qū)ο蠓椒芮邢嚓P的新特點,從而具體化為下列的面向?qū)ο笤O計準則。11.1面向?qū)ο笤O計的準則1.模塊化面向?qū)ο筌浖_發(fā)模式,很自然地支持了把系統(tǒng)分解成模塊的設計原理:對象就是模塊。它是把數(shù)據(jù)結構和操作這些數(shù)據(jù)的方法緊密地結合在一起所構成的模塊。2.抽象面向?qū)ο蠓椒ú粌H支持過程抽象,而且支持數(shù)據(jù)抽象。類實際上是一種抽象數(shù)據(jù)類型,它對外開放的公共接口構成了類的規(guī)格說明(即協(xié)議),這種接口規(guī)定了外界可以使用的合法操作符,利用這些操作符可以對類實例中包含的數(shù)據(jù)進行操作。使用者無須知道這些操作符的實現(xiàn)算法和類中數(shù)據(jù)元素的具體表示方法,就可以通過這些操作符使用類中定義的數(shù)據(jù)。通常把這類抽象稱為規(guī)格說明抽象。此外,某些面向?qū)ο蟮某绦蛟O計語言還支持參數(shù)化抽象。所謂參數(shù)化抽象,是指當描述類的規(guī)格說明時并不具體指定所要操作的數(shù)據(jù)類型,而是把數(shù)據(jù)類型作為參數(shù)。這使得類的抽象程度更高,應用范圍更廣,可重用性更高。例如,C++語言提供的“模板”機制就是一種參數(shù)化抽象機制。3.信息隱藏在面向?qū)ο蠓椒ㄖ?,信息隱藏通過對象的封裝性實現(xiàn):類結構分離了接口與實現(xiàn),從而支持了信息隱藏。對于類的用戶來說,屬性的表示方法和操作的實現(xiàn)算法都應該是隱藏的。4.弱耦合耦合指一個軟件結構內(nèi)不同模塊之間互連的緊密程度。在面向?qū)ο蠓椒ㄖ?,對象是最基本的模塊,因此,耦合主要指不同對象之間相互關聯(lián)的緊密程度。弱耦合是優(yōu)秀設計的一個重要標準,因為這有助于使得系統(tǒng)中某一部分的變化對其他部分的影響降到最低程度。在理想情況下,對某一部分的理解、測試或修改,無須涉及系統(tǒng)的其他部分。如果一類對象過多地依賴其他類對象來完成自己的工作,則不僅給理解、測試或修改這個類帶來很大困難,而且還將大大降低該類的可重用性和可移植性。顯然,類之間的這種相互依賴關系是緊耦合的。當然,對象不可能是完全孤立的,當兩個對象必須相互聯(lián)系相互依賴時,應該通過類的協(xié)議(即公共接口)實現(xiàn)耦合,而不應該依賴于類的具體實現(xiàn)細節(jié)。一般說來,對象之間的耦合可分為兩大類,下面分別討論這兩類耦合:(1)交互耦合如果對象之間的耦合通過消息連接來實現(xiàn),則這種耦合就是交互耦合。為使交互耦合盡可能松散,應該遵守下述準則:盡量降低消息連接的復雜程度。應該盡量減少消息中包含的參數(shù)個數(shù),降低參數(shù)的復雜程度。減少對象發(fā)送(或接收)的消息數(shù)。(2)繼承耦合與交互耦合相反,應該提高繼承耦合程度。繼承是一般化類與特殊類之間耦合的一種形式。從本質(zhì)上看,通過繼承關系結合起來的基類和派生類,構成了系統(tǒng)中粒度更大的模塊。因此,它們彼此之間應該結合得越緊密越好。為獲得緊密的繼承耦合,特殊類應該確實是對它的一般化類的一種具體化。因此,如果一個派生類摒棄了它基類的許多屬性,則它們之間是松耦合的。在設計時應該使特殊類盡量多繼承并使用其一般化類的屬性和服務,從而更緊密地耦合到其一般化類。5.強內(nèi)聚內(nèi)聚衡量一個模塊內(nèi)各個元素彼此結合的緊密程度。也可以把內(nèi)聚定義為:設計中使用的一個構件內(nèi)的各個元素,對完成一個定義明確的目的所做出的貢獻程度。在設計時應該力求做到高內(nèi)聚。在面向?qū)ο笤O計中存在下述3種內(nèi)聚。(1)服務內(nèi)聚。一個服務應該完成一個且僅完成一個功能。(2)類內(nèi)聚。設計類的原則是,一個類應該只有一個用途,它的屬性和服務應該是高內(nèi)聚的。類的屬性和服務應該全都是完成該類對象的任務所必需的,其中不包含無用的屬性或服務。如果某個類有多個用途,通常應該把它分解成多個專用的類。(3)一般-特殊內(nèi)聚。設計出的一般-特殊結構,應該符合多數(shù)人的概念,更準確地說,這種結構應該是對相應的領域知識的正確抽取。一般說來,緊密的繼承耦合與高度的一般-特殊內(nèi)聚是一致的。6.可重用軟件重用是提高軟件開發(fā)生產(chǎn)率和目標系統(tǒng)質(zhì)量的重要途徑。重用基本上從設計階段開始。重用有兩方面的含義:一是盡量使用已有的類(包括開發(fā)環(huán)境提供的類庫,及以往開發(fā)類似系統(tǒng)時創(chuàng)建的類),二是如果確實需要創(chuàng)建新類,則在設計這些新類的協(xié)議時,應該考慮將來的可重復使用性。關于軟件重用問題,將在11.3節(jié)進一步討論。人們使用面向?qū)ο蠓椒▽W開發(fā)軟件的歷史雖然不長,但也積累了一些經(jīng)驗。總結這些經(jīng)驗得出了幾條啟發(fā)規(guī)則,它們往往能幫助軟件開發(fā)人員提高面向?qū)ο笤O計的質(zhì)量。1.設計結果應該清晰易懂使設計結果清晰、易讀、易懂,是提高軟件可維護性和可重用性的重要措施。顯然,人們不會重用那些他們不理解的設計。保證設計結果清晰易懂的主要因素如下。11.2啟發(fā)規(guī)則(1)用詞一致。應該使名字與它所代表的事物一致,而且應該盡量使用人們習慣的名字。不同類中相似服務的名字應該相同。(2)使用已有的協(xié)議。如果開發(fā)同一軟件的其他設計人員已經(jīng)建立了類的協(xié)議,或者在所使用的類庫中已有相應的協(xié)議,則應該使用這些已有的協(xié)議。(3)減少消息模式的數(shù)目。如果已有標準的消息協(xié)議,設計人員應該遵守這些協(xié)議。如果確需自己建立消息協(xié)議,則應該盡量減少消息模式的數(shù)目,只要可能,就使消息具有一致的模式,以利于讀者理解。(4)避免模糊的定義。一個類的用途應該是有限的,而且應該從類名可以較容易地推想出它的用途。2.一般-特殊結構的深度應適當應該使類等級中包含的層次數(shù)適當。一般說來,在一個中等規(guī)模(大約包含100個類)的系統(tǒng)中,類等級層次數(shù)應保持為7±2。不應該僅僅從方便編碼的角度出發(fā)隨意創(chuàng)建派生類,應該使一般-特殊結構與領域知識或常識保持一致。3.設計簡單的類應該盡量設計小而簡單的類,以便于開發(fā)和管理。當類很大的時候,要記住它的所有服務是非常困難的。經(jīng)驗表明,如果一個類的定義不超過一頁紙(或兩屏),則使用這個類是比較容易的。為使類保持簡單,應該注意以下幾點。(1)避免包含過多的屬性。屬性過多通常表明這個類過分復雜了,它所完成的功能可能太多了。(2)有明確的定義。為了使類的定義明確,分配給每個類的任務應該簡單,最好能用一兩個簡單語句描述它的任務。(3)盡量簡化對象之間的合作關系。如果需要多個對象協(xié)同配合才能做好一件事,則破壞了類的簡明性和清晰性。(4)不要提供太多服務。一個類提供的服務過多,同樣表明這個類過分復雜。典型地,一個類提供的公共服務不超過7個。在開發(fā)大型軟件系統(tǒng)時,遵循上述啟發(fā)規(guī)則也會帶來另一個問題:設計出大量較小的類,這同樣會帶來一定復雜性。解決這個問題的辦法,是把系統(tǒng)中的類按邏輯分組,也就是劃分“主題”。4.使用簡單的協(xié)議一般說來,消息中的參數(shù)不要超過3個。當然,不超過3個的限制也不是絕對的,但是,經(jīng)驗表明,通過復雜消息相互關聯(lián)的對象是緊耦合的,對一個對象的修改往往導致其他對象的修改。5.使用簡單的服務面向?qū)ο笤O計出來的類中的服務通常都很小,一般只有3~5行源程序語句,可以用僅含一個動詞和一個賓語的簡單句子描述它的功能。如果一個服務中包含了過多的源程序語句,或者語句嵌套層次太多,或者使用了復雜的CASE語句,則應該仔細檢查這個服務,設法分解或簡化它。一般說來,應該盡量避免使用復雜的服務。如果需要在服務中使用CASE語句,通常應該考慮用一般-特殊結構代替這個類的可能性。6.把設計變動減至最小通常,設計的質(zhì)量越高,設計結果保持不變的時間也越長。即使出現(xiàn)必須修改設計的情況,也應該使修改的范圍盡可能小。理想的設計變動曲線如圖11.1所示。在設計的早期階段,變動較大,隨著時間推移,設計方案日趨成熟,改動也越來越小了。圖11.1中的峰值與出現(xiàn)設計錯誤或發(fā)生非預期變動的情況相對應。峰值越高,表明設計質(zhì)量越差,可重用性也越差。圖11.1理想的設計變動情況1.重用重用也叫再用或復用,是指同一事物不作修改或稍加改動就多次重復使用。廣義地說,軟件重用可分為以下3個層次:11.3軟件重用
11.3.1概述(1)知識重用(例如,軟件工程知識的重用)。(2)方法和標準的重用(例如,面向?qū)ο蠓椒ɑ驀抑贫ǖ能浖_發(fā)規(guī)范的重用)。(3)軟件成分的重用。前兩個重用層次屬于知識工程研究的范疇,本節(jié)僅討論軟件成分重用問題。2.軟件成分的重用級別軟件成分的重用可以進一步劃分成以下3個級別:(1)代碼重用人們談論得最多的是代碼重用,通常把它理解為調(diào)用庫中的模塊。實際上,代碼重用也可以采用下列幾種形式中的任何一種:源代碼剪貼:這是最原始的重用形式。這種重用方式的缺點,是復制或修改原有代碼時可能出錯,更糟糕的是,存在嚴重的配置管理問題,人們幾乎無法跟蹤原始代碼塊多次修改重用的過程。源代碼包含:許多程序設計語言都提供包含(include)庫中源代碼的機制。使用這種重用形式時,配置管理問題有所緩解,因為修改了庫中源代碼之后,所有包含它的程序自然都必須重新編譯。繼承:利用繼承機制重用類庫中的類時,無須修改已有的代碼,就可以擴充或具體化在庫中找出的類,因此,基本上不存在配置管理問題。(2)設計結果重用設計結果重用指的是,重用某個軟件系統(tǒng)的設計模型(即求解域模型)。這個級別的重用有助于把一個應用系統(tǒng)移植到完全不同的軟硬件平臺上。(3)分析結果重用這是一種更高級別的重用,即重用某個系統(tǒng)的分析模型。這種重用特別適用于用戶需求未改變,但系統(tǒng)體系結構發(fā)生了根本變化的場合。3.典型的可重用軟件成分更具體地說,可能被重用的軟件成分主要有以下10種:(1)項目計劃。軟件項目計劃的基本結構和許多內(nèi)容(例如,軟件質(zhì)量保證計劃)都是可以跨項目重用的。這樣做減少了用于制定計劃的時間,也降低了與建立進度表和進行風險分析等活動相關聯(lián)的不確定性。(2)成本估計。因為在不同項目中經(jīng)常含有類似的功能,所以有可能在只做極少修改或根本不做修改的情況下,重用對該功能的成本估計結果。(3)體系結構。即使在考慮不同的應用領域時,也很少有截然不同的程序和數(shù)據(jù)體系結構。因此,有可能創(chuàng)建一組類屬的體系結構模板(例如,事務處理體系結構),并把那些模板作為可重用的設計框架。通常把類屬的體系結構模板稱為領域體系結構。(4)需求模型和規(guī)格說明。類和對象的模型及規(guī)格說明是明顯的重用的候選者,此外,用傳統(tǒng)軟件工程方法開發(fā)的分析模型(例如,數(shù)據(jù)流圖),也是可重用的。(5)設計。用傳統(tǒng)方法開發(fā)的體系結構、數(shù)據(jù)、接口和過程設計結果,是重用的候選者,更常見的是,系統(tǒng)和對象設計是可重用的。(6)源代碼。用兼容的程序設計語言書寫的、經(jīng)過驗證的程序構件,是重用的候選者。(7)用戶文檔和技術文檔。即使針對的應用是不同的,也經(jīng)常有可能重用用戶文檔和技術文檔的大部分。(8)用戶界面。這可能是最廣泛被重用的軟件成分,GUI(圖形用戶界面)軟件經(jīng)常被重用。因為它可占到一個應用程序的60%代碼量,因此,重用的效果非常顯著。(9)數(shù)據(jù)。在大多數(shù)經(jīng)常被重用的軟件成分中,被重用的數(shù)據(jù)包括:內(nèi)部表、列表和記錄結構,以及文件和完整的數(shù)據(jù)庫。(10)測試用例。一旦設計或代碼構件將被重用,相關的測試用例應該“附屬于”它們也被重用。利用面向?qū)ο蠹夹g,可以更方便更有效地實現(xiàn)軟件重用。面向?qū)ο蠹夹g中的“類”,是比較理想的可重用軟構件,不妨稱之為類構件。類構件有3種重用方式,分別是實例重用、繼承重用和多態(tài)重用。下面進一步講述與類構件有關的內(nèi)容。11.3.2類構件1.可重用軟構件應具備的特點為使軟構件也像硬件集成電路那樣,能在構造各種各樣的軟件系統(tǒng)時方便地重復使用,就必須使它們滿足下列要求。(1)模塊獨立性強。具有單一、完整的功能,且經(jīng)過反復測試被確認是正確的。它應該是一個不受或很少受外界干擾的封裝體,其內(nèi)部實現(xiàn)在外面是不可見的。(2)具有高度可塑性。軟構件的應用環(huán)境比集成電路更廣闊、更復雜。顯然,要求一個軟構件能滿足任何一個系統(tǒng)的設計需求是不現(xiàn)實的。因此,可重用的軟構件必須具有高度可裁剪性,也就是說,必須提供為適應特定需求而擴充或修改已有構件的機制,而且所提供的機制必須使用起來非常簡單方便。(3)接口清晰、簡明、可靠。軟構件應該提供清晰、簡明、可靠的對外接口,而且還應該有詳盡的文檔說明,以方便用戶使用。精心設計的“類”基本上能滿足上述要求,可以認為它是可重用軟構件的雛形。2.類構件的重用方式(1)實例重用由于類的封裝性,使用者無須了解實現(xiàn)細節(jié)就可以使用適當?shù)臉嬙旌瘮?shù),按照需要創(chuàng)建類的實例。然后向所創(chuàng)建的實例發(fā)送適當?shù)南?,啟動相應的服務,完成需要完成的工作。這是最基本的重用方式。此外,還可以用幾個簡單的對象作為類的成員創(chuàng)建出一個更復雜的類,這是實例重用的另一種形式。雖然實例重用是最基本的重用方式,但是,設計出一個理想的類構件并不是一件容易的事情。例如,決定一個類對外提供多少服務就是一件相當困難的事。提供的服務過多,會增加接口復雜度,也會使類構件變得難于理解;提供的服務過少,則會因為過分一般化而失去重用價值。每個類構件的合理服務數(shù)都與具體應用環(huán)境密切相關,因此找到一個合理的折衷值是相當困難的。(2)繼承重用面向?qū)ο蠓椒ㄌ赜械睦^承性提供了一種對已有的類構件進行裁剪的機制。當已有的類構件不能通過實例重用完全滿足當前系統(tǒng)需求時,繼承重用提供了一種安全地修改已有類構件,以便在當前系統(tǒng)中重用的手段。為提高繼承重用的效果,關鍵是設計一個合理的、具有一定深度的類構件繼承層次結構。這樣做有下述兩個好處:每個子類在繼承父類的屬性和服務的基礎上,只加入少量新屬性和新服務,這就不僅降低了每個類構件的接口復雜度,表現(xiàn)出一個清晰的進化過程,提高了每個子類的可理解性,而且為軟件開發(fā)人員提供了更多可重用的類構件。因此,在軟件開發(fā)過程中,應該時刻注意提取這種潛在的可重用構件,必要時應在領域?qū)<規(guī)椭?,建立符合領域知識的繼承層次。為多態(tài)重用奠定了良好基礎。(3)多態(tài)重用利用多態(tài)性不僅可以使對象的對外接口更加一般化(基類與派生類的許多對外接口是相同的),從而降低了消息連接的復雜程度,而且還提供了一種簡便可靠的軟構件組合機制。系統(tǒng)運行時,根據(jù)接收消息的對象類型,由多態(tài)性機制啟動正確的方法,去響應一個一般化的消息,從而簡化了消息界面和軟構件連接過程。為充分實現(xiàn)多態(tài)重用,在設計類構件時,應該把注意力集中在下列一些可能影響重用性的操作上:與表示方法有關的操作。例如,不同實例的比較、顯示、擦除等等。與數(shù)據(jù)結構、數(shù)據(jù)大小等有關的操作。與外部設備有關的操作。例如,設備控制。實現(xiàn)算法在將來可能會改進(或改變)的核心操作。如果不預先采取適當措施,上述這些操作會妨礙類構件的重用。還可以把適配接口再進一步細分為轉(zhuǎn)換接口和擴充接口。轉(zhuǎn)換接口,是為了克服與表示方法、數(shù)據(jù)結構或硬件特點相關的操作給重用帶來的困難而設計的,這類接口是每個類構件在重用時都必須重新定義的服務的集合。當使用C++語言編程時,應該在根類(或適當?shù)幕?中,把屬于轉(zhuǎn)換接口的服務定義為純虛函數(shù)。如果某個服務有多種可能的實現(xiàn)算法,則應該把它當作擴充接口。擴充接口與轉(zhuǎn)換接口不同,并不需要強迫用戶在派生類中重新定義它們,相反,如果在派生類中沒有給出擴充接口的新算法,則將繼承父類中的算法。當用C++語言實現(xiàn)時,在基類中把這類服務定義為普通的虛函數(shù)。1.質(zhì)量理想情況下,為了重用而開發(fā)的軟件構件已被證明是正確的,且沒有缺陷。事實上,由于不能定期進行形式化驗證,錯誤可能而且也確實存在。但是,隨著每一次重用,都會有一些錯誤被發(fā)現(xiàn)并被清除,構件的質(zhì)量也會隨之改善。隨著時間的推移,構件將變成實質(zhì)上無錯誤的。11.3.3軟件重用的效益2.生產(chǎn)率當把可重用的軟件成分應用于軟件開發(fā)的全過程時,創(chuàng)建計劃、模型、文檔、代碼和數(shù)據(jù)所需花費的時間將減少,從而將用較少的投入給客戶提供相同級別的產(chǎn)品,因此,生產(chǎn)率得到了提高。由于應用領域、問題復雜程度、項目組的結構和大小、項目期限、可應用的技術等許多因素都對項目組的生產(chǎn)率有影響,因此,不同開發(fā)組織對軟件重用帶來生產(chǎn)率提高的數(shù)字的報告并不相同,但基本上30%~50%的重用大約可以導致生產(chǎn)率提高25%~40%。3.成本軟件重用帶來的凈成本節(jié)省可以用下式估算:C=Cs-Cr-Cd其中,Cs是項目從頭開發(fā)(沒有重用)時所需要的成本;Cr是與重用相關聯(lián)的成本;Cd是交付給客戶的軟件的實際成本??梢允褂帽緯?3章講述的技術來估算Cs,而與重用相關聯(lián)的成本Cr主要包括下述成本:領域分析與建模的成本;設計領域體系結構的成本;為便于重用而增加的文檔的成本;維護和完善可重用的軟件成分的成本;為從外部獲取構件所付出的版稅和許可證費;創(chuàng)建(或購買)及運行重用庫的費用;對設計和實現(xiàn)可重用構件的人員的培訓費用。雖然和領域分析及運行重用庫相關聯(lián)的成本可能相當高,但是它們可以由許多項目分攤。上面列出的很多其他成本所解決的問題,實際上是良好軟件工程實踐的一部分,不管是否優(yōu)先考慮重用,這些問題都應該解決。人類解決復雜問題時普遍采用的策略是,“分而治之,各個擊破”。同樣,軟件工程師在設計比較復雜的應用系統(tǒng)時普遍采用的策略,也是首先把系統(tǒng)分解成若干個比較小的部分,然后再分別設計每個部分。這樣做有利于降低設計的難度,有利于分工協(xié)作,也有利于維護人員對系統(tǒng)理解和維護。系統(tǒng)的主要組成部分稱為子系統(tǒng)。通常根據(jù)所提供的功能來劃分子系統(tǒng)。一般說來,子系統(tǒng)的數(shù)目應該與系統(tǒng)規(guī)模基本匹配。11.4系統(tǒng)分解各個子系統(tǒng)之間應該具有盡可能簡單、明確的接口。接口確定了交互形式和通過子系統(tǒng)邊界的信息流,但是無須規(guī)定子系統(tǒng)內(nèi)部的實現(xiàn)算法。因此,可以相對獨立地設計各個子系統(tǒng)。在劃分和設計子系統(tǒng)時,應該盡量減少子系統(tǒng)彼此間的依賴性。采用面向?qū)ο蠓椒ㄔO計軟件系統(tǒng)時,面向?qū)ο笤O計模型(即求解域的對象模型),與面向?qū)ο蠓治瞿P?即問題域的對象模型)一樣,也由主題、類與對象、結構、屬性、服務等5個層次組成。這5個層次一層比一層表示的細節(jié)更多,可以把這5個層次想象為整個模型的水平切片。此外,大多數(shù)系統(tǒng)的面向?qū)ο笤O計模型,在邏輯上都由4大部分組成。這4大部分對應于組成目標系統(tǒng)的4個子系統(tǒng),它們分別是問題域子系統(tǒng)、人機交互子系統(tǒng)、任務管理子系統(tǒng)和數(shù)據(jù)管理子系統(tǒng)。當然,在不同的軟件系統(tǒng)中,這四個子系統(tǒng)的重要程度和規(guī)模可能相差很大,規(guī)模過大的在設計過程中應該進一步劃分成更小的子系統(tǒng),規(guī)模過小的可合并在其他子系統(tǒng)中。某些領域的應用系統(tǒng)在邏輯上可能僅由3個(甚至少于3個)子系統(tǒng)組成。可以把面向?qū)ο笤O計模型的4大組成部分想象成整個模型的4個垂直切片。典型的面向?qū)ο笤O計模型可以用圖11.2表示。圖11.2典型的面向?qū)ο笤O計模型1.子系統(tǒng)之間的兩種交互方式在軟件系統(tǒng)中,子系統(tǒng)之間的交互有兩種可能的方式,分別是客戶-供應商(Client-supplier)關系和平等伙伴(peer-to-peer)關系。(1)客戶-供應商關系在這種關系中,作為“客戶”的子系統(tǒng)調(diào)用作為“供應商”的子系統(tǒng),后者完成某些服務工作并返回結果。使用這種交互方案,作為客戶的子系統(tǒng)必須了解作為供應商的子系統(tǒng)的接口,然而后者卻無須了解前者的接口,因為任何交互行為都是由前者驅(qū)動的。(2)平等伙伴關系在這種關系中,每個子系統(tǒng)都可能調(diào)用其他子系統(tǒng),因此,每個子系統(tǒng)都必須了解其他子系統(tǒng)的接口。由于各個子系統(tǒng)需要相互了解對方的接口,因此這種組織系統(tǒng)的方案比起客戶-供應商方案來,子系統(tǒng)之間的交互更復雜,而且這種交互方式還可能存在通信環(huán)路,從而使系統(tǒng)難于理解,容易發(fā)生不易察覺的設計錯誤??偟恼f來,單向交互比雙向交互更容易理解,也更容易設計和修改,因此應該盡量使用客戶-供應商關系。2.組織系統(tǒng)的兩種方案把子系統(tǒng)組織成完整的系統(tǒng)時,有水平層次組織和垂直塊組織兩種方案可供選擇。(1)層次組織這種組織方案把軟件系統(tǒng)組織成一個層次系統(tǒng),每層是一個子系統(tǒng)。上層在下層的基礎上建立,下層為實現(xiàn)上層功能而提供必要的服務。每一層內(nèi)所包含的對象,彼此間相互獨立,而處于不同層次上的對象,彼此間往往有關聯(lián)。實際上,在上、下層之間存在客戶-供應商關系。低層子系統(tǒng)提供服務,相當于供應商,上層子系統(tǒng)使用下層提供的服務,相當于客戶。層次結構又可進一步劃分成兩種模式:封閉式和開放式。所謂封閉式,就是每層子系統(tǒng)僅僅使用其直接下層提供的服務。由于一個層次的接口只影響與其緊相鄰的上一層,因此,這種工作模式降低了各層次之間的相互依賴性,更容易理解和修改。在開放模式中,某層子系統(tǒng)可以使用處于其下面的任何一層子系統(tǒng)所提供的服務。這種工作模式的優(yōu)點,是減少了需要在每層重新定義的服務數(shù)目,使得整個系統(tǒng)更高效更緊湊。但是,開放模式的系統(tǒng)不符合信息隱藏原則,對任何一個子系統(tǒng)的修改都會影響處在更高層次的那些子系統(tǒng)。設計軟件系統(tǒng)時到底采用哪種結構模式,需要權衡效率和模塊獨立性等多種因素,通盤考慮以后再做決定。通常,在需求陳述中只描述了對系統(tǒng)頂層和底層的需求,頂層就是用戶看到的目標系統(tǒng),底層則是可以使用的資源。這兩層往往差異很大,設計者必須設計一些中間層次,以減少不同層次之間的概念差異。(2)塊狀組織這種組織方案把軟件系統(tǒng)垂直地分解成若干個相對獨立的、弱耦合的子系統(tǒng),一個子系統(tǒng)相當于一塊,每塊提供一種類型的服務。利用層次和塊的各種可能的組合,可以成功地由多個子系統(tǒng)組成一個完整的軟件系統(tǒng)。當混合使用層次結構和塊狀結構時,同一層次可以由若干塊組成,而同一塊也可以分為若干層。例如,圖11.3表示一個應用系統(tǒng)的組織結構,這個應用系統(tǒng)采用了層次與塊狀的混合結構。3.設計系統(tǒng)的拓撲結構由子系統(tǒng)組成完整的系統(tǒng)時,典型的拓撲結構有管道形、樹形、星形等。設計者應該采用與問題結構相適應的、盡可能簡單的拓撲結構,以減少子系統(tǒng)之間的交互數(shù)量。圖11.3典型應用系統(tǒng)的組織結構使用面向?qū)ο蠓椒ㄩ_發(fā)軟件時,在分析與設計之間并沒有明確的分界線,對于問題域子系統(tǒng)來說,情況更是如此。但是,分析與設計畢竟是性質(zhì)不同的兩類開發(fā)工作,分析工作可以而且應該與具體實現(xiàn)無關,設計工作則在很大程度上受具體實現(xiàn)環(huán)境的約束。在開始進行設計工作之前(至少在完成設計之前),設計者應該了解本項目預計要使用的編程語言,可用的軟構件庫(主要是類庫)以及程序員的編程經(jīng)驗。11.5設計問題域子系統(tǒng)通過面向?qū)ο蠓治鏊贸龅膯栴}域精確模型,為設計問題域子系統(tǒng)奠定了良好的基礎,建立了完整的框架。只要可能,就應該保持面向?qū)ο蠓治鏊⒌膯栴}域結構。通常,面向?qū)ο笤O計僅需從實現(xiàn)角度對問題域模型做一些補充或修改,主要是增添、合并或分解類與對象、屬性及服務,調(diào)整繼承關系等等。當問題域子系統(tǒng)過分復雜龐大時,應該把它進一步分解成若干個更小的子系統(tǒng)。使用面向?qū)ο蠓椒▽W開發(fā)軟件,能夠保持問題域組織框架的穩(wěn)定性,從而便于追蹤分析、設計和編程的結果。在設計與實現(xiàn)過程中所做的細節(jié)修改(例如,增加具體類,增加屬性或服務),并不影響開發(fā)結果的穩(wěn)定性,因為系統(tǒng)的總體框架是基于問題域的。對于需求可能隨時間變化的系統(tǒng)來說,穩(wěn)定性是至關重要的。穩(wěn)定性也是能夠在類似系統(tǒng)中重用分析、設計和編程結果的關鍵因素。為更好地支持系統(tǒng)在其生命期中的擴充,也同樣需要穩(wěn)定性。下面介紹,在面向?qū)ο笤O計過程中,可能對面向?qū)ο蠓治鏊贸龅膯栴}域模型做的補充或修改。1.調(diào)整需求有兩種情況會導致修改通過面向?qū)ο蠓治鏊_定的系統(tǒng)需求:一是用戶需求或外部環(huán)境發(fā)生了變化;二是分析員對問題域理解不透徹或缺乏領域?qū)<規(guī)椭灾旅嫦驅(qū)ο蠓治瞿P筒荒芡暾?、準確地反映用戶的真實需求。無論出現(xiàn)上述哪種情況,通常都只需簡單地修改面向?qū)ο蠓治鼋Y果,然后再把這些修改反映到問題域子系統(tǒng)中。2.重用已有的類代碼重用從設計階段開始,在研究面向?qū)ο蠓治鼋Y果時就應該尋找使用已有類的方法。若因為沒有合適的類可以重用而確實需要創(chuàng)建新的類,則在設計這些新類的協(xié)議時,必須考慮到將來的可重用性。如果有可能重用已有的類,則重用已有類的典型過程如下:(1)選擇有可能被重用的已有類,標出這些候選類中對本問題無用的屬性和服務,盡量重用那些能使無用的屬性和服務降到最低程度的類。(2)在被重用的已有類和問題域類之間添加泛化關系(即從被重用的已有類派生出問題域類)。(3)標出問題域類中從已有類繼承來的屬性和服務,現(xiàn)在已經(jīng)無須在問題域類內(nèi)定義它們了。(4)修改與問題域類相關的關聯(lián),必要時改為與被重用的已有類相關的關聯(lián)。3.把問題域類組合在一起在面向?qū)ο笤O計過程中,設計者往往通過引入一個根類而把問題域類組合在一起。事實上,這是在沒有更先進的組合機制可用時才采用的一種組合方法。此外,這樣的根類還可以用來建立協(xié)議。4.增添一般化類以建立協(xié)議在設計過程中常常發(fā)現(xiàn),一些具體類需要有一個公共的協(xié)議,也就是說,它們都需要定義一組類似的服務。在這種情況下可以引入一個附加類(例如,根類),以便建立這個協(xié)議(即命名公共服務集合,這些服務在具體類中仔細定義)。5.調(diào)整繼承層次如果面向?qū)ο蠓治瞿P椭邪硕嘀乩^承關系,然而所使用的程序設計語言卻并不提供多重繼承機制,則必須修改面向?qū)ο蠓治龅慕Y果。即使使用支持多重繼承的語言,有時也會出于實現(xiàn)考慮而對面向?qū)ο蠓治鼋Y果作一些調(diào)整。下面分幾種情況討論:(1)使用多重繼承機制使用多重繼承機制時,應該避免出現(xiàn)屬性及服務的命名沖突。下面通過例子說明避免命名沖突的方法。圖11.4是一種多重繼承模式的例子,這種模式可以稱為窄菱形模式。使用這種模式時出現(xiàn)屬性及服務命名沖突的可能性比較大。圖11.5(見書262頁)是另一種多重繼承模式,稱為闊菱形模式。使用這種模式時,屬性及服務的名字發(fā)生沖突的可能性比較小,但是,它需要用更多的類才能表示同一個設計。圖11.4窄菱形模式(2)使用單繼承機制如果打算使用僅提供單繼承機制的語言實現(xiàn)系統(tǒng),則必須把面向?qū)ο蠓治瞿P椭械亩嘀乩^承結構轉(zhuǎn)換成單繼承結構。常見的做法是,把多重繼承結構簡化成單一的單繼承層次結構,如圖11.6所示。顯然,在多重繼承結構中的某些繼承關系,經(jīng)簡化后將不再存在,這表明需要在各個具體類中重復定義某些屬性和服務。圖11.6把多重繼承簡化為單一層次的單繼承6.ATM系統(tǒng)實例圖11.7描繪了上章給出的ATM系統(tǒng)的問題域子系統(tǒng)的結構。由于在面向?qū)ο蠓治鲞^程中已經(jīng)對ATM系統(tǒng)做了相當仔細的分析,而且假設所使用的實現(xiàn)環(huán)境能完全支持面向?qū)ο蠓治瞿P偷膶崿F(xiàn),因此,在面向?qū)ο笤O計階段無須對已有的問題域模型作實質(zhì)性的修改或擴充。圖11.7ATM系統(tǒng)問題域子系統(tǒng)的結構在面向?qū)ο蠓治鲞^程中,已經(jīng)對用戶界面需求做了初步分析,在面向?qū)ο笤O計過程中,則應該對系統(tǒng)的人機交互子系統(tǒng)進行詳細設計,以確定人機交互的細節(jié),其中包括指定窗口和報表的形式、設計命令層次等項內(nèi)容。11.6設計人機交互子系統(tǒng)人機交互部分的設計結果,將對用戶情緒和工作效率產(chǎn)生重要影響。人機界面設計得好,則會使系統(tǒng)對用戶產(chǎn)生吸引力,用戶在使用系統(tǒng)的過程中會感到興奮,能夠激發(fā)用戶的創(chuàng)造力,提高工作效率;相反,人機界面設計得不好,用戶在使用過程中就會感到不方便、不習慣,甚至會產(chǎn)生厭煩和惱怒的情緒。由于對人機界面的評價,在很大程度上由人的主觀因素決定,因此,使用由原型支持的系統(tǒng)化的設計策略,是成功地設計人機交互子系統(tǒng)的關鍵。本節(jié)僅從面向?qū)ο笤O計的角度補充講述一下設計人機交互子系統(tǒng)的策略。1.分類用戶人機交互界面是給用戶使用的,顯然,為設計好人機交互子系統(tǒng),設計者應該認真研究使用它的用戶。應該深入到用戶的工作現(xiàn)場,仔細觀察用戶是怎樣做他們的工作的,這對設計好人機交互界面是非常必要的。為了更好地了解用戶的需要與愛好,以便設計出符合用戶需要的界面,設計者首先應該把將來可能與系統(tǒng)交互的用戶分類。通常從下列幾個不同角度進行分類:按技能水平分類(新手、初級、中級、高級)。按職務分類(總經(jīng)理、經(jīng)理、職員)。按所屬集團分類(職員、顧客)。2.描述用戶應該仔細了解將來使用系統(tǒng)的每類用戶的情況,把獲得的下列各項信息記錄下來:用戶類型。使用系統(tǒng)欲達到的目的。特征(年齡、性別、受教育程度、限制因素等)。關鍵的成功因素(需求、愛好、習慣等)。技能水平。完成本職工作的腳本。3.設計命令層次設計命令層次的工作通常包含以下幾項內(nèi)容。(1)研究現(xiàn)有的人機交互含義和準則現(xiàn)在,Windows已經(jīng)成了微機上圖形用戶界面事實上的工業(yè)標準。所有Windows應用程序的基本外觀及給用戶的感受都是相同的。Windows程序通常還遵守廣大用戶習以為常的許多約定。設計圖形用戶界面時,應該保持與普通Windows應用程序界面相一致,并遵守廣大用戶習慣的約定,這樣才會被用戶接受和喜愛。(2)確定初始的命令層次所謂命令層次,實質(zhì)上是用過程抽象機制組織起來的、可供選用的服務的表示形式。設計命令層次時,通常先從對服務的過程抽象著手,然后再進一步修改它們,以適合具體應用環(huán)境的需要。(3)精化命令層次為進一步修改完善初始的命令層次,應該考慮下列一些因素:次序:仔細選擇每個服務的名字,并在命令層的每一部分內(nèi)把服務排好次序。排序時或者把最常用的服務放在最前面,或者按照用戶習慣的工作步驟排序。整體-部分關系:尋找在這些服務中存在的整體-部分模式,這樣做有助于在命令層中分組組織服務。寬度和深度:由于人的短期記憶能力有限,命令層次的寬度和深度都不應該過大。操作步驟:應該用盡量少的單擊、拖動和擊鍵組合來表達命令,而且應該為高級用戶提供簡捷的操作方法。4.設計人機交互類人機交互類與所使用的操作系統(tǒng)及編程語言密切相關。例如,在Windows環(huán)境下運行的VisualC++語言提供了MFC類庫,設計人機交互類時,往往僅需從MFC類庫中選出一些適用的類,然后從這些類派生出符合自己需要的類就可以了。雖然從概念上說,不同對象可以并發(fā)地工作,但是,在實際系統(tǒng)中,許多對象之間往往存在相互依賴關系。此外,在實際使用的硬件中,可能僅由一個處理器支持多個對象。因此,設計工作的一項重要內(nèi)容就是,確定哪些是必須同時動作的對象,哪些是相互排斥的對象。然后進一步設計任務管理子系統(tǒng)。11.7設計任務管理子系統(tǒng)1.分析并發(fā)性通過面向?qū)ο蠓治鼋⑵饋淼膭討B(tài)模型,是分析并發(fā)性的主要依據(jù)。如果兩個對象彼此間不存在交互,或者它們同時接受事件,則這兩個對象在本質(zhì)上是并發(fā)的。通過檢查各個對象的狀態(tài)圖及它們之間交換的事件,能夠把若干個非并發(fā)的對象歸并到一條控制線中。所謂控制線,是一條遍及狀態(tài)圖集合的路徑,在這條路徑上每次只有一個對象是活動的。在計算機系統(tǒng)中用任務(task)實現(xiàn)控制線,一般認為任務是進程(process)的別名。通常把多個任務的并發(fā)執(zhí)行稱為多任務。對于某些應用系統(tǒng)來說,通過劃分任務,可以簡化系統(tǒng)的設計及編碼工作。不同的任務標識了必須同時發(fā)生的不同行為。這種并發(fā)行為既可以在不同的處理器上實現(xiàn),也可以在單個處理器上利用多任務操作系統(tǒng)仿真實現(xiàn)(通常采用時間分片策略仿真多處理器環(huán)境)。2.設計任務管理子系統(tǒng)常見的任務有事件驅(qū)動型任務、時鐘驅(qū)動型任務、優(yōu)先任務、關鍵任務和協(xié)調(diào)任務等。設計任務管理子系統(tǒng),包括確定各類任務并把任務分配給適當?shù)挠布蜍浖?zhí)行。(1)確定事件驅(qū)動型任務某些任務是由事件驅(qū)動的,這類任務可能主要完成通信工作。例如,與設備、屏幕窗口、其他任務、子系統(tǒng)、另一個處理器或其他系統(tǒng)通信。事件通常是表明某些數(shù)據(jù)到達的信號。在系統(tǒng)運行時,這類任務的工作過程如下:任務處于睡眠狀態(tài)(不消耗處理器時間),等待來自數(shù)據(jù)線或其他數(shù)據(jù)源的中斷;一旦接收到中斷就喚醒了該任務,接收數(shù)據(jù)并把數(shù)據(jù)放入內(nèi)存緩沖區(qū)或其他目的地,通知需要知道這件事的對象,然后該任務又回到睡眠狀態(tài)。(2)確定時鐘驅(qū)動型任務某些任務每隔一定時間間隔就被觸發(fā)以執(zhí)行某些處理,例如,某些設備需要周期性地獲得數(shù)據(jù);某些人機接口、子系統(tǒng)、任務、處理器或其他系統(tǒng)也可能需要周期性地通信。在這些場合往往需要使用時鐘驅(qū)動型任務。時鐘驅(qū)動型任務的工作過程如下:任務設置了喚醒時間后進入睡眠狀態(tài);任務睡眠(不消耗處理器時間),等待來自系統(tǒng)的中斷;一旦接收到這種中斷,任務就被喚醒并做它的工作,通知有關的對象,然后該任務又回到睡眠狀態(tài)。(3)確定優(yōu)先任務優(yōu)先任務可以滿足高優(yōu)先級或低優(yōu)先級的處理需求:高優(yōu)先級:某些服務具有很高的優(yōu)先級,為了在嚴格限定的時間內(nèi)完成這種服務,可能需要把這類服務分離成獨立的任務。低優(yōu)先級:與高優(yōu)先級相反,有些服務是低優(yōu)先級的,屬于低優(yōu)先級處理(通常指那些背景處理)。設計時可能用額外的任務把這樣的處理分離出來。(4)確定關鍵任務關鍵任務是有關系統(tǒng)成功或失敗的關鍵處理,這類處理通常都有嚴格的可靠性要求。在設計過程中可能用額外的任務把這樣的關鍵處理分離出來,以滿足高可靠性處理的要求。對高可靠性處理應該精心設計和編碼,并且應該嚴格測試。(5)確定協(xié)調(diào)任務當系統(tǒng)中存在3個以上任務時,就應該增加一個任務,用它作為協(xié)調(diào)任務。引入?yún)f(xié)調(diào)任務會增加系統(tǒng)的總開銷(增加從一個任務到另一個任務的轉(zhuǎn)換時間),但是引入?yún)f(xié)調(diào)任務有助于把不同任務之間的協(xié)調(diào)控制封裝起來。使用狀態(tài)轉(zhuǎn)換矩陣可以比較方便地描述該任務的行為。這類任務應該僅做協(xié)調(diào)工作,不要讓它再承擔其他服務工作。(6)盡量減少任務數(shù)必須仔細分析和選擇每個確實需要的任務。應該使系統(tǒng)中包含的任務數(shù)盡量少。設計多任務系統(tǒng)的主要問題是,設計者常常為了自己處理時的方便而輕率地定義過多的任務。這樣做加大了設計工作的技術復雜度,并使系統(tǒng)變得不易理解,從而也加大了系統(tǒng)維護的難度。(7)確定資源需求使用多處理器或固件,主要是為了滿足高性能的需求。設計者必須通過計算系統(tǒng)載荷(即每秒處理的業(yè)務數(shù)及處理一個業(yè)務所花費的時間),來估算所需要的CPU(或其他固件)的處理能力。設計者應該綜合考慮各種因素,以決定哪些子系統(tǒng)用硬件實現(xiàn),哪些子系統(tǒng)用軟件實現(xiàn)。下述兩個因素可能是使用硬件實現(xiàn)某些子系統(tǒng)的主要原因:現(xiàn)有的硬件完全能滿足某些方面的需求,例如,買一塊浮點運算卡比用軟件實現(xiàn)浮點運算要容易得多。專用硬件比通用的CPU性能更高。例如,目前在信號處理系統(tǒng)中廣泛使用固件實現(xiàn)快速傅里葉變換。設計者在決定到底采用軟件還是硬件的時候,必須綜合權衡一致性、成本、性能等多種因素,還要考慮未來的可擴充性和可修改性。數(shù)據(jù)管理子系統(tǒng)是系統(tǒng)存儲或檢索對象的基本設施,它建立在某種數(shù)據(jù)存儲管理系統(tǒng)之上,并且隔離了數(shù)據(jù)存儲管理模式(文件、關系數(shù)據(jù)庫或面向?qū)ο髷?shù)據(jù)庫)的影響。11.8設計數(shù)據(jù)管理子系統(tǒng)不同的數(shù)據(jù)存儲管理模式有不同的特點,適用范圍也不相同,設計者應該根據(jù)應用系統(tǒng)的特點選擇適用的模式。1.文件管理系統(tǒng)文件管理系統(tǒng)是操作系統(tǒng)的一個組成部分,使用它長期保存數(shù)據(jù)具有成本低和簡單等特點,但是,文件操作的級別低,為提供適當?shù)某橄蠹墑e還必須編寫額外的代碼。此外,不同操作系統(tǒng)的文件管理系統(tǒng)往往有明顯差異。11.8.1選擇數(shù)據(jù)存儲管理模式2.關系數(shù)據(jù)庫管理系統(tǒng)關系數(shù)據(jù)庫管理系統(tǒng)的理論基礎是關系代數(shù),它不僅理論基礎堅實而且有下列一些主要優(yōu)點:(1)提供了各種最基本的數(shù)據(jù)管理功能(例如,中斷恢復,多用戶共享,多應用共享,完整性,事務支持等)。(2)為多種應用提供了一致的接口。(3)標準化的語言(大多數(shù)商品化關系數(shù)據(jù)庫管理系統(tǒng)都使用SQL語言)。但是,為了做到通用與一致,關系數(shù)據(jù)庫管理系統(tǒng)通常都相當復雜,且有下述一些具體缺點,以致限制了這種系統(tǒng)的普遍使用:(1)運行開銷大:即使只完成簡單的事務(例如,只修改表中的一行),也需要較長的時間。(2)不能滿足高級應用的需求:關系數(shù)據(jù)庫管理系統(tǒng)是為商務應用服務的,商務應用中數(shù)據(jù)量雖大但數(shù)據(jù)結構卻比較簡單。事實上,關系數(shù)據(jù)庫管理系統(tǒng)很難用在數(shù)據(jù)類型豐富或操作不標準的應用中。(3)與程序設計語言的連接不自然:SQL語言支持面向集合的操作,是一種非過程性語言;然而大多數(shù)程序設計語言本質(zhì)上卻是過程性的,每次只能處理一個記錄。3.面向?qū)ο髷?shù)據(jù)庫管理系統(tǒng)面向?qū)ο髷?shù)據(jù)庫管理系統(tǒng)是一種新技術,主要有兩種設計途徑:擴展的關系數(shù)據(jù)庫管理系統(tǒng)和擴展的面向?qū)ο蟪绦蛟O計語言。(1)擴展的關系數(shù)據(jù)庫管理系統(tǒng)是在關系數(shù)據(jù)庫的基礎上,增加了抽象數(shù)據(jù)類型和繼承機制,此外還增加了創(chuàng)建及管理類和對象的通用服務。(2)擴展的面向?qū)ο蟪绦蛟O計語言擴充了面向?qū)ο蟪绦蛟O計語言的語法和功能,增加了在數(shù)據(jù)庫中存儲和管理對象的機制。開發(fā)人員可以用統(tǒng)一的面向?qū)ο笥^點進行設計,不再需要區(qū)分存儲數(shù)據(jù)結構和程序數(shù)據(jù)結構(即生命期短暫的數(shù)據(jù))。目前,大多數(shù)“對象”數(shù)據(jù)管理模式都采用“復制對象”的方法:先保留對象值,然后,在需要時創(chuàng)建該對象的一個副本。擴展的面向?qū)ο蟪绦蛟O計語言則擴充了這種機制,它支持“永久對象”方法:準確存儲對象(包括對象的內(nèi)部標識在內(nèi)),而不是僅僅存儲對象值。使用這種方法,當從存儲器中檢索出一個對象的時候,它就完全等同于原先存在的那個對象。“永久對象”方法,為在多用戶環(huán)境中從對象服務器中共享對象奠定了基礎。設計數(shù)據(jù)管理子系統(tǒng),既需要設計數(shù)據(jù)格式又需要設計相應的服務。1.設計數(shù)據(jù)格式設計數(shù)據(jù)格式的方法與所使用的數(shù)據(jù)存儲管理模式密切相關,下面分別介紹適用于每種數(shù)據(jù)存儲管理模式的設計方法:(1)文件系統(tǒng)定義第一范式表:列出每個類的屬性表;把屬性表規(guī)范成第一范式,從而得到第一范式表的定義。11.8.2設計數(shù)據(jù)管理子系統(tǒng)為每個第一范式表定義一個文件。測量性能和需要的存儲容量。修改原設計的第一范式,以滿足性能和存儲需求。必要時把泛化結構的屬性壓縮在單個文件中,以減少文件數(shù)量。必要時把某些屬性組合在一起,并用某種編碼值表示這些屬性,而不再分別使用獨立的域表示每個屬性。這樣做可以減少所需要的存儲空間,但是增加了處理時間。(2)關系數(shù)據(jù)庫管理系統(tǒng)定義第三范式表:列出每個類的屬性表;把屬性表規(guī)范成第三范式,從而得出第三范式表的定義。為每個第三范式表定義一個數(shù)據(jù)庫表。測量性能和需要的存儲容量。修改先前設計的第三范式,以滿足性能和存儲需求。(3)面向?qū)ο髷?shù)據(jù)庫管理系統(tǒng)擴展的關系數(shù)據(jù)庫途徑:使用與關系數(shù)據(jù)庫管理系統(tǒng)相同的方法。擴展的面向?qū)ο蟪绦蛟O計語言途徑:不需要規(guī)范化屬性的步驟,因為數(shù)據(jù)庫管理系統(tǒng)本身具有把對象值映射成存儲值的功能。2.設計相應的服務如果某個類的對象需要存儲起來,則在這個類中增加一個屬性和服務,用于完成存儲對象自身的工作。應該把為此目的增加的屬性和服務作為“隱含”的屬性和服務,即無須在面向?qū)ο笤O計模型的屬性和服務層中顯式地表示它們,僅需在關于類與對象的文檔中描述它們。這樣設計之后,對象將知道怎樣存儲自己。用于“存儲自己”的屬性和服務,在問題域子系統(tǒng)和數(shù)據(jù)管理子系統(tǒng)之間構成一座必要的橋梁。利用多重繼承機制,可以在某個適當?shù)幕愔卸x這樣的屬性和服務,然后,如果某個類的對象需要長期存儲,該類就從基類中繼承這樣的屬性和服務。下面介紹使用不同數(shù)據(jù)存儲管理模式時的設計要點。(1)文件系統(tǒng)被存儲的對象需要知道打開哪個(些)文件,怎樣把文件定位到正確的記錄上,怎樣檢索出舊值(如果有的話),以及怎樣用現(xiàn)有值更新它們。此外,還應該定義一個ObjectServer(對象服務器)類,并創(chuàng)建它的實例。該類提供下列服務:通知對象保存自身;檢索已存儲的對象(查找,讀值,創(chuàng)建并初始化對象),以便把這些對象提供給其他子系統(tǒng)使用。注意,為提高性能應該批量處理訪問文件的要求。(2)關系數(shù)據(jù)庫管理系統(tǒng)被存儲的對象,應該知道訪問哪些數(shù)據(jù)庫表,怎樣訪問所需要的行,怎樣檢索出舊值(如果有的話),以及怎樣用現(xiàn)有值更新它們。此外,還應該定義一個ObjectServer類,并聲明它的對象。該類提供下列服務:通知對象保存自身;檢索已存儲的對象(查找,讀值,創(chuàng)建并初始化對象),以便由其他子系統(tǒng)使用這些對象。(3)面向?qū)ο髷?shù)據(jù)庫管理系統(tǒng)擴展的關系數(shù)據(jù)庫途徑:與使用關系數(shù)據(jù)庫管理系統(tǒng)時方法相同。擴展的面向?qū)ο蟪绦蛟O計語言途徑:無須增加服務,這種數(shù)據(jù)庫管理系統(tǒng)已經(jīng)給每個對象提供了“存儲自己”的行為。只需給需要長期保存的對象加個標記,然后由面向?qū)ο髷?shù)據(jù)庫管理系統(tǒng)負責存儲和恢復這類對象。為具體說明數(shù)據(jù)管理子系統(tǒng)的設計方法,讓我們再看看圖11.7所示的ATM系統(tǒng)。從圖中可以看出,惟一的永久性數(shù)據(jù)存儲放在分行計算機中。因為必須保持數(shù)據(jù)的一致性和完整性,而且常常有多個并發(fā)事務同時訪問這些數(shù)據(jù),因此,采用成熟的商品化關系數(shù)據(jù)庫管理系統(tǒng)存儲數(shù)據(jù)。應該把每個事務作為一個不可分割的批操作來處理,由事務封鎖賬戶直到該事務結束為止。11.8.3例子在這個例子中,需要存儲的對象主要是賬戶類的對象。為了支持數(shù)據(jù)管理子系統(tǒng)的實現(xiàn),賬戶類對象必須知道自己是怎樣存儲的,有兩種方法可以達到這個目的。(1)每個對象自己保存自己賬戶類對象在接到“存儲自己”的通知后,知道怎樣把自身存儲起來(需要增加一個屬性和一個服務來定義上述行為)。(2)由數(shù)據(jù)管理子系統(tǒng)負責存儲對象賬戶類對象在接到“存儲自己”的通知后,知道應該向數(shù)據(jù)管理子系統(tǒng)發(fā)送什么消息,以便由數(shù)據(jù)管理子系統(tǒng)把它的狀態(tài)保存起來,為此也需要增加屬性和服務來定義上述行為。使用這種方法的優(yōu)點,是無須修改問題域子系統(tǒng)。如上一小節(jié)所述,應該定義一個數(shù)據(jù)管理類ObjectServer,并聲明它的對象。這個類提供下列服務:通知對象保存自身或保存需長期存儲的對象的狀態(tài);檢索已存儲的對象并使之“復活”。需要綜合考慮對象模型、動態(tài)模型和功能模型,才能正確確定類中應有的服務。對象模型是進行對象設計的基本框架。但是,面向?qū)ο蠓治龅贸龅膶ο竽P?,通常只在每個類中列出很少幾個最核心的服務。設計者必須把動態(tài)模型中對象的行為以及功能模型中的數(shù)據(jù)處理,轉(zhuǎn)換成由適當?shù)念愃峁┑姆铡?1.9設計類中的服務
11.9.1設計類中應有的服務一張狀態(tài)圖描繪了一類對象的生命周期,圖中的狀態(tài)轉(zhuǎn)換是執(zhí)行對象服務的結果。對象的許多服務都與對象接收到的事件密切相關,事實上,事件就表現(xiàn)為消息,接收消息的對象必然有由消息選擇符指定的服務,該服務改變對象狀態(tài)(修改相應的屬性值),并完成對象應做的動作。對象的動作既與事件有關,也與對象的狀態(tài)有關。因此,完成服務的算法自然也和對象的狀態(tài)有關。如果一個對象在不同狀態(tài)可以接受同樣事件,而且在不同狀態(tài)接收到同樣事件時其行為不同,則實現(xiàn)服務的算法中需要有一個依賴于狀態(tài)的DO-CASE型控制結構。功能模型指明了系統(tǒng)必須提供的服務。狀態(tài)圖中狀態(tài)轉(zhuǎn)換所觸發(fā)的動作,在功能模型中有時可能擴展成一張數(shù)據(jù)流圖。數(shù)據(jù)流圖中的某些處理可能與對象提供的服務相對應,下列規(guī)則有助于確定操作的目標對象(即應該在該對象所屬的類中定義這個服務):(1)如果某個處理的功能是從輸入流中抽取一個值,則該輸入流就是目標對象。(2)如果某個處理具有類型相同的輸入流和輸出流,而且輸出流實質(zhì)上是輸入流的另一種形式,則該輸入輸出流就是目標對象。(3)如果某個處理從多個輸入流得出輸出值,則該處理是輸出類中定義的一個服務。(4)如果某個處理把對輸入流處理的結果輸出給數(shù)據(jù)存儲或動作對象,則該數(shù)據(jù)存儲或動作對象就是目標對象。當一個處理涉及多個對象時,為確定把它作為哪個對象的服務,設計者必須判斷哪個對象在這個處理中起主要作用。通常在起主要作用的對象類中定義這個服務。下面兩條規(guī)則有助于確定處理的歸屬:(1)如果處理影響或修改了一個對象,則最好把該處理與處理的目標(而不是觸發(fā)者)聯(lián)系在一起。(2)考察處理涉及的對象類及這些類之間的關聯(lián),從中找出處于中心地位的類。如果其他類和關聯(lián)圍繞這個中心類構成星形,則這個中心類就是處理的目標。在面向?qū)ο笤O計過程中還應該進一步設計實現(xiàn)服務的方法,主要應該完成以下幾項工作。1.設計實現(xiàn)服務的算法設計實現(xiàn)服務的算法時,應該考慮下列幾個因素:(1)算法復雜度。通常選用復雜度較低(即效率較高)的算法,但也不要過分追求高效率,應以能滿足用戶需求為準。11.9.2設計實現(xiàn)服務的方法(2)容易理解與容易實現(xiàn)。容易理解與容易實現(xiàn)的要求往往與高效率有矛盾,設計者應該對這兩個因素適當折衷。(3)易修改。應該盡可能預測將來可能做的修改,并在設計時預先做些準備。2.選擇數(shù)據(jù)結構在分析階段,僅需考慮系統(tǒng)中需要的信息的邏輯結構,在面向?qū)ο笤O計過程中,則需要選擇能夠方便、有效地實現(xiàn)算法的物理數(shù)據(jù)結構。3.定義內(nèi)部類和內(nèi)部操作在面向?qū)ο笤O計過程中,可能需要增添一些在需求陳述中沒有提到的類,這些新增加的類,主要用來存放在執(zhí)行算法過程中所得出的某些中間結果。此外,復雜操作往往可以用簡單對象上的更低層操作來定義。因此,在分解高層操作時常常引入新的低層操作。在面向?qū)ο笤O計過程中應該定義這些新增加的低層操作。在對象模型中,關聯(lián)是聯(lián)結不同對象的紐帶,它指定了對象相互間的訪問路徑。在面向?qū)ο笤O計過程中,設計人員必須確定實現(xiàn)關聯(lián)的具體策略。既可以選定一個全局性的策略統(tǒng)一實現(xiàn)所有關聯(lián),也可以分別為每個關聯(lián)選擇具體的實現(xiàn)策略,以與它在應用系統(tǒng)中的使用方式相適應。為了更好地設計實現(xiàn)關聯(lián)的途徑,首先應該分析使用關聯(lián)的方式。11.10設計關聯(lián)1.關聯(lián)的遍歷在應用系統(tǒng)中,使用關聯(lián)有兩種可能的方式:單向遍歷和雙向遍歷。在應用系統(tǒng)中,某些關聯(lián)只需要單向遍歷,這種單向關聯(lián)實現(xiàn)起來比較簡單,另外一些關聯(lián)可能需要雙向遍歷,雙向關聯(lián)實現(xiàn)起來稍微麻煩一些。在使用原型法開發(fā)軟件的時候,原型中所有關聯(lián)都應該是雙向的,以便于增加新的行為,快速地擴充和修改原型。2.實現(xiàn)單向關聯(lián)用指針可以方便地實現(xiàn)單向關聯(lián)。如果關聯(lián)的重數(shù)是一元的(如圖11.8所示),則實現(xiàn)關聯(lián)的指針是一個簡單指針;如果重數(shù)是多元的,則需要用一個指針集合實現(xiàn)關聯(lián)(參見圖11.9)。圖11.8用指針實現(xiàn)單向關聯(lián)圖11.9用指針實現(xiàn)雙向關聯(lián)3.實現(xiàn)雙向關聯(lián)許多關聯(lián)都需要雙向遍歷,當然,兩個方向遍歷的頻度往往并不相同。實現(xiàn)雙向關聯(lián)有下列3種方法:(1)只用屬性實現(xiàn)一個方向的關聯(lián),當需要反向遍歷時就執(zhí)行一次正向查找。如果兩個方向遍歷的頻度相差很大,而且需要盡量減少存儲開銷和修改時的開銷,則這是一種很有效的實現(xiàn)雙向關聯(lián)的方法。圖11.10用對象實現(xiàn)關聯(lián)(2)兩個方向的關聯(lián)都用屬性實現(xiàn)。具體實現(xiàn)方法已在前面講過,如圖11.9所示。這種方法能實現(xiàn)快速訪問,但是,如果修改了一個屬性,則相關的屬性也必須隨之修改,才能保持該關聯(lián)鏈的一致性。當訪問次數(shù)遠遠多于修改次數(shù)時,這種實現(xiàn)方法很有效。(3)用獨立的關聯(lián)對象實現(xiàn)雙向關聯(lián)。關聯(lián)對象不屬于相互關聯(lián)的任何一個類,它是獨立的關聯(lián)類的實例,如圖11.10所示。4.關聯(lián)對象的實現(xiàn)可以引入一個關聯(lián)類來保存描述關聯(lián)性質(zhì)的信息,關聯(lián)中的每個連接對應著關聯(lián)類的一個對象。實現(xiàn)關聯(lián)對象的方法取決于關聯(lián)的重數(shù)。對于一對一關聯(lián)來說,關聯(lián)對象可以與參與關聯(lián)的任一個對象合并。對于一對多關聯(lián)來說,關聯(lián)對象可以與“多”端對象合并。如果是多對多關聯(lián),則關聯(lián)鏈的性質(zhì)不可能只與一個參與關聯(lián)的對象有關,通常用一個獨立的關聯(lián)類來保存描述關聯(lián)性質(zhì)的信息,這個類的每個實例表示一條具體的關聯(lián)鏈及該鏈的屬性。系統(tǒng)的各項質(zhì)量指標并不是同等重要的,設計人員必須確定各項質(zhì)量指標的相對重要性(即確定優(yōu)先級),以便在優(yōu)化設計時制定折衷方案。11.11設計優(yōu)化
11.11.1確定優(yōu)先級系統(tǒng)的整體質(zhì)量與設計人員所制定的折衷方案密切相關。最終產(chǎn)品成功與否,在很大程度上取決于是否選擇好了系統(tǒng)目標。最糟糕的情況是,沒有站在全局高度正確確定各項質(zhì)量指標的優(yōu)先級,以致系統(tǒng)中各個子系統(tǒng)按照相互對立的目標做了優(yōu)化,將導致系統(tǒng)資源的嚴重浪費。在折衷方案中設置的優(yōu)先級應該是模糊的。事實上,不可能指定精確的優(yōu)先級數(shù)值(例如,速度48%,內(nèi)存25%,費用8%,可修改性19%)。最常見的情況,是在效率和清晰性之間尋求適當?shù)恼壑苑桨浮O旅鎯尚」?jié)分別講述在優(yōu)化設計時提高效率的技術,以及建立良好的繼承結構的方法。1.增加冗余關聯(lián)以提高訪問效率在面向?qū)ο蠓治鲞^程中,應該避免在對象模型中存在冗余的關聯(lián),因為冗余關聯(lián)不僅沒有增添任何信息,反而會降低模型的清晰程度。但是,在面向?qū)ο笤O計過程中,應當考慮用戶的訪問模式,及不同類型的訪問彼此間的依賴關系時,就會發(fā)現(xiàn),分析階段確定的關聯(lián)可能并沒有構成效率最高的訪問路徑。下面用設計公司雇員技能數(shù)據(jù)庫的例子,說明分析訪問路徑及提高訪問效率的方法。11.11.2提高效率的幾項技術圖11.11是從面向?qū)ο蠓治瞿P椭姓〉囊徊糠?。公司類中的服務find_skill返回具有指定技能的雇員集合。例如,用戶可能詢問公司中會講日語的雇員有哪些人。假設某公司共有2000名雇員,平均每名雇員會10種技能,則簡單的嵌套查詢將遍歷雇員對象2000次,針對每名雇員平均再遍歷技能對象10次。如果全公司僅有5名雇員精通日語,則查詢命中率僅有1/4000。圖11.11公司、雇員及技能之間的關聯(lián)鏈提高訪問效率的一種方法是使用哈希(Hash)表:“具有技能”這個關聯(lián)不再利用無序表實現(xiàn),而是改用哈希表實現(xiàn)。只要“會講日語”是用惟一一個技能對象表示,這樣改進后就會使查詢次數(shù)由20000次減少到2000次。但是,當僅有極少數(shù)對象滿足查詢條件時,查詢命中率仍然很低。在這種情況下,更有效的提高查詢效率的改進方法是,給那些需要經(jīng)常查詢的對象建立索引。例如,針對上述例子,可以增加一個額外的限定關聯(lián)“精通語言”,用來聯(lián)系公司與雇員這兩類對象,如圖11.12所示。利用適當?shù)娜哂嚓P聯(lián),可以立即查到精通某種具體語言的雇員,而無須多余的訪問。當然,索引也必然帶來開銷:占用內(nèi)存空間,而且每當修改基關聯(lián)時也必須相應地修改索引。因此,應該只給那些經(jīng)常執(zhí)行并且開銷大、命中率低的查詢建立索引。圖11.12為雇員技能數(shù)據(jù)庫建立索引2.調(diào)整查詢次序改進了對象模型的結構,從而優(yōu)化了常用的遍歷之后,接下來就應該優(yōu)化算法了。優(yōu)化算法的一個途徑是盡量縮小查找范圍。例如,假設用戶在使用上述的雇員技能數(shù)據(jù)庫的過程中,希望找出既會講日語又會講法語的所有雇員。如果某公司只有5位雇員會講日語,會講法語的雇員卻有200人,則應該先查找會講日語的雇員,然后再從這些會講日語的雇員中查找同時又會講法語的人。3.保留派生屬性通過某種運算而從其
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度別墅建筑工程材料供應合同3篇
- 二零二五年船舶貨物運輸合同印花稅繳納指南3篇
- 二零二五年度產(chǎn)權式酒店預售合同書3篇
- 二零二五年度工業(yè)廠房買賣附帶配套設施租賃合同模板二3篇
- 2025年中國尼龍油墨市場運營態(tài)勢分析及投資前景預測報告
- 二零二五年稻草生物質(zhì)能源開發(fā)與市場推廣合同2篇
- 2024版商業(yè)禮品合作協(xié)議樣本
- 2024版?zhèn)€人借款給公司的借款合同
- 2025年房產(chǎn)居間代理協(xié)議5篇
- 二零二五版加油站能源管理系統(tǒng)合同3篇
- 《道路車輛 48V供電電壓的電氣及電子部件 電性能要求和試驗方法》文本以及編制說明
- 十八項醫(yī)療核心制度考試題與答案
- 2024年鄂爾多斯市國資產(chǎn)投資控股集團限公司招聘管理單位遴選500模擬題附帶答案詳解
- 篝火晚會流程
- 船形烏頭提取工藝優(yōu)化
- 財務總監(jiān)個人述職報告
- 居家養(yǎng)老護理人員培訓方案
- 江蘇省無錫市2024年中考語文試卷【附答案】
- 管理者的九大財務思維
- 四年級上冊數(shù)學應用題練習100題附答案
- 2024年度中國電建集團北京勘測設計研究院限公司校園招聘高頻難、易錯點500題模擬試題附帶答案詳解
評論
0/150
提交評論