引言
統一建模語言(Unified Modeling Language,簡寫為UML)是一種通用的模擬語言,它可以用於確定、展示和記錄軟件系統的設計過程。統一建模語言中的圖形標記,尤其是用於面向對象的軟件設計。它有兩大優點:
(1)UML是國際軟件工業界廣泛認可的標准,它統一了對象模擬的標記和含義,使軟件設計工具能發揮更大的功用,同時,現有的對象設計也能更容易地被重新使用。
(2)UML博采眾長,設當地平衡了簡潔性和具體化兩個總之,UML已經成為一種單獨的系統來演化,不像以前的多種標准的體系引起的問題。
所以,作為軟件開發者,完全有必要學習、了解UML。本文就提供了一個案例研究,我只是想利用這個案例研究給大家一個對UML的感性認識,了解在現實世界中如何使用 UML來編寫應用程序。所以我想找了一個相對比較復雜的案例,找來找去,發現圖書館中處理借出以及預借書籍和雜志的應用程序是相當大的例子,足以說明UML如何在現實世界中使用。
我只是利用使用案例(use case)和討論域分析來分析描述一個分析模型中的應用,我把它擴展成一個設計模型,用來描述技術解決方案的一個代表部分, 最後,我們再用Java語言進行編碼。但請記住,我給出的只是一種可能的解決方案,還有許多其他的解決方案需要您用聰明的頭腦去發掘,而且這世界上也沒有適合所有的情況的解決方案。當然,某些解決方案會比其他的要好,但那只有有了足夠的經驗和遇到的許多困難的事並解決之後才會積累下來知識。好,下面我們進入案例研究。
要求
一般情況下,是使用系統的最終用戶的代表人來書寫要求規范,對於圖書館應用程序,要求規范應該如下:
1、圖書館應用程序應當是圖書館的支持系統。
2、圖書館把書籍和雜志借給借書者(讀者)的條件當然是讀者應當在該系統中注冊過,同樣書籍和雜志也應當在系統中注冊過。
3、圖書館處理購買新書或雜志的操作,暢銷書或雜志應當多購幾本,舊的書籍和雜志當它們過時或殘破時就應適當把它們從書架上請下來。
4、圖書管理員是圖書館中的職員,他的職責就是與顧客 (借書者)打交道並通過該系統完成工作。
5、借書者可以預借一本當前不在圖書館中的書籍或雜志,當這本書被歸還或被購入圖書館的時候,他就會接到通知;當借書者借到這本書或雜志的時候,預定就會被取消;也可以使用顯示程序取消預借。
6、圖書館可以很容易地創建,更新和刪除系統中的書名,借書者,借閱情況以及預借情況等信息
7、該系統可以運行於所有流行的操作系統,包括 UNIX, Windows以及 OS/2,它還應當有先進的友好的圖形用戶界面 ( GUI )。
8、該系統應當很容易使用新的功能擴展。
在本案例分析中,該系統的第一個版本不需要處理某個讀者預借的書籍成為可借書籍時發送消息給讀者的操作,也不需要檢查某本書籍是否已經超時了。
分析
分析的目的是為了獲得和描述系統中所有的要求,以及生成一個在該系統中定義關鍵域類的模型。其目標是在開發者與制定要求的人之間建立相互理解和溝通,因此分析是一種典型的與用戶或客戶合作的行為。在這個階段開發者不應該考慮具體的代碼或程序細節; 這只是真正地理解要求和正在設計的系統的實際情況的第一步。
第一節 分析要求
分析的第一步應當是判斷該系統將被用於做什麼以及誰將使用它。這分別是所謂的使用案例(use case)和行動者(actor)。使用案例描述了圖書館系統具體應當提供哪些功能,即系統的功能要求。一個使用案例分析過程包括閱讀和分析規范,並且討論該系統的潛在的用戶 (客戶)。圖書館中的行動者是圖書管理員和借書者,圖書管理員是該系統的用戶而借書者則是顧客,查看並且預訂書籍和雜志的人應該是借書者,但是有時候也可能是一個圖書管理員或另外一個圖書館。借書者並不需要直接與系統打交道,借書者的功能通過圖書管理員來代理完成。
圖書館系統的使用案例是:
借書
還書
生成預訂
刪除預訂
增加書目
更新或刪除書目
添加書籍
刪除書籍
添加借書者
更新或刪除借書者
因為圖書館中的一種暢銷書常常有好幾本,所以系統必須把暢銷書從普通書目中區別開來。
如果借書者沒有預借書籍:
識別像要借的書的書名。
識別館中本書目前可借的書籍
識別借書者
圖書館借出這本書。
登記剛剛發生的借出情況。
如果借書者曾預借某本書籍:
識別借書者。
識別預借的書名。
識別館中本書目前可借的書籍。
圖書館借給借書人相應的書。
登記借出情況 。
刪除預借書籍的紀錄。
除用於定義本系統的功能要求之外,使用案例還被用來分析檢查適當的討論域類是否已經被定義,以及在設計過程中它們是否能被用來確認該技術解決方案能夠處理所需要功能。使用案例可以在序列圖上看見,來實現一些技術細節。
第二節 討論域分析
分析過程中還要詳細地列舉討論域 (domain ,系統中關鍵的類 ),為了進行討論域分析,需要充分理解規范和使用案例並且著眼於系統將要處理的 "概念 "; 或者與使用者及討論域專家組織一次集體研討會談,嘗試找出所有必須處理的關鍵概念以及它們之間的相互關系。
圖書館系統中的討論域類如下:: BorrowerInformation(這樣命名是為了區別於使用案例圖表中的行動者 Borrower), Title, Book Title, Magazine, Item, Reservation和 Loan。 圖 2是一張類圖,標出它們的相互關系。這些討論域類是用戶自定義的類,指定該類的對象是關鍵域的一部分並將被持久的保存在系統中。
圖二解釋:域類結構。 域分析要詳細列舉系統中的關鍵的類。 對於每一個對象,它調用另外一個對象上的方法,就要在類之間加上一根線來說明它們的關系。每個用來表示類的矩形框被橫向隔成三部分。 最上面一格是類的名稱,中間是類的屬性,最下面一格是類的方法。 兩個類之間的關聯用一根實現連接代表,象征一個對象調用了另外一個對象的方法。如果你仔細觀察,還會發現在Loan和Item關聯的Loan端的"0..1",代表那一端可取的對象數。
一些類用UML狀態圖來顯示這些類的對象的不同狀態以及能夠使它們的狀態改變的事件,如本文中的例子就是Item和 Title。圖 3就是借書(Lend Item)的使用案例的序列圖 (借書者沒有預借書籍 )。
圖三解釋:借書情景的序列圖。本情景給出的是使用案例的特定的過程,情景總是以一個行動者為開端,即系統以外的人。然後記錄通過系統直到以所有的行動者角度來看這個的行動都已完成的完整的路線。用於標注一個情景的UML記號法就是序列圖。這張序列圖用來說明一個情景,即借書者沒有預借某本書時的借書情景。
當我們給序列圖建模的時候,很明顯,我們需要給行動者提供一個與窗口或對話框的接口界面。在本案例分析中,為了把窗口類從討論域類中區分開的,就把窗口類放入一個名為 " GUI Package "的包中,而把討論域類放入一個名為" Business Package "的包,應當明確需要提供借書、預借書籍和還書界面窗口,此時還不需要定義具體的用戶界面。
設計
當已經考慮了所有的技術細節和限制條件,我們就可以進入設計階段,設計階段需要展開和細化分析模型。設計的目的是為了說明一種可以很容易地翻譯成程序設計代碼的工作解決方案。
設計階段可以分成兩部分:
1、結構設計 這是非常高級的設計,說明在什麼地方定義包(子系統),以及包與包之間的相互依賴與通信機制。自然,我們的目標是構建一種清晰而又簡單的體系結構,包與包之間的依賴要少,如果可能的話,盡量避免雙向的依賴。
2、詳細設計 所有的類都應描述足夠的細節,來明確規定誰來編碼這些類。 UML中的動態模型用於示范類的對象在具體的環境中的行為。
下面我將詳細說明。
第一節 結構設計
一個設計良好的體系結構是開發一個可擴展、可改變的系統的基礎,程序包所需要關心的是要麼處理一個具體的功能區域,要麼處理一個具體的技術區域。從技術邏輯中把應用程序邏輯(域類)區分開來是極其重要的,這是為了萬一需要修改程序的某一部分而不會對另一部分產生影響:一個目標就是標識並設定包與包之間(例如“子系統”)的相互依賴的規則,並不在包之間創建雙向的依賴(為了避免程序包集成的太過緊密),另一個目標是為了表示標准類庫的需要。現在可用的應用程序庫強調的主要還是在技術領域,比如用戶界面,數據庫或通信機制等等,但是,我們也同樣盼望出現更多的具體的應用程序庫。
本案例研究中的程序包或者說是子系統如下:
1、用戶界面包(User-Interface) 這些類都是基於 Java AWT包這個Java中用於編寫用戶界面應用程序的一個標准的類庫。這個程序包與商業對象包(Business Object)協作,商業對象包包含了實際上用於儲存數據用的類,用戶界面包調用商業對象中的方法來取得並向商業對象中插入數據。
2、商業對象包(Business Object) 它包括來自分析模型,比如 BorrowerInformation, Title, Item, Loan等等的討論域類。 該設計完全地定義了它們的操作並且添加了對於持久性的支持。 商業對象包與數據庫包合作,所有的商業對象類都必須從數據庫包中的 Persistent類繼承而來。
3、數據庫包 (Database Package) 數據庫包給商業對象包中的另外一個類提供服務,以使它們能夠持久的儲存信息。在目前的版本,Persistent類將儲存它的子類對象到文件系統中的文件中去。
4、實用程序包(Utility Package) 實用程序包包含用於該系統中的另外一個包的服務,現在,該包中只有 ObjId類,它用於引用遍及本系統的持久對象,包括用戶界面,商業對象和數據庫包。
這些程序包的內部設計見圖 4。
圖4解釋 圖書館應用程序結構概圖。 這是一張類圖,說明應用程序包以及它們之間的關系。數據庫包提供了持久性,公用程序包提供了Object ID類,商業對象包包含了討論域類,這點在圖5中將詳細列出。最後,基於標准Java AWT類庫的UI包調用商業對象中的操作來向它們中間插入數據。
第二節 詳細設計
詳細設計描述新的類--在用戶界面和數據庫包中的類,以及在本分析中描繪的商業對象類以外的人。本類的狀態和動態圖表使用的是與分析過程中一樣的圖表,但是它們被定義在更加詳細和更高的技術層次,分析過程中的使用案例描述用於驗證在設計階段處理的使用案例,使用序列圖表闡明在系統中,每個使用案例是如何在技術上實現的。
數據庫包 應用程序必須有持久儲存對象,所以必須添加一個數據庫層來提供這個服務,為了簡單起見,我們把對象作為文件儲存在磁盤上,關於存儲器的細節就不需要被應用程序所知了,它調用通用操作,比如 store()、update()、delete()和 find()等等,這些都是一個調用 Persistent的類的一部分,所有的類都需要繼承 Persistent(持久對象)。
持久性處理中的一個重要的因素就是 ObjId類,它的對象用於引用任何系統中的持久對象 (無論對象是在磁盤上還是已經被讀入應用程序中了 )。 ObjId是Object Identity的簡寫,是一種熟知的技術,用於處理應用程序中的對象引用。 通過使用對象標識,一個對象標識號就能被傳遞到 Persistent.getObject ( )操作,然後該對象將從持久存儲器中取回。 通常,這要通過每個持久類中的 getObject操作來完成,它還要執行必要的類型檢查和轉換。對象標識號還可以很容易地作為操作的參數被傳遞 (例如,一個尋找具體對象的搜索窗口可以通過對象標識號傳遞它的結果到另外一個窗口 )。
ObjId標識系統(用戶界面、商業對象和數據庫)中所有的包使用的一個常規類,因此它在設計階段就被放進實用程序包中而不是數據庫包中。Persistent類的當前實現還可以不夠完善,它的最終目標是可以很容易的改變持久存儲器的實現,目前的替代的辦法是把對象出存在關系數據庫或面向對象數據庫中,也可以使用Java中的持久對象支持儲存它們。
商業對象包 在設計階段中的商業對象包基於分析過程中相應的包——討論域類。類以及它們的相互關系和行為沒有變,但是類被描述的更加詳細,包括了它們的相互關系和行為如何實現。
一些操作已經被翻譯成好幾個設計模型中的操作,一些還被改了名稱,這都是很正常的,因為分析只是每個類的能力的描繪,而設計則是系統詳細的描述,因此設計模型中的所有的操作都必須有定義好的特征和返回值,注意,下面給出了設計與分析的不同。
圖5解釋 商業對象設計。 這張圖表充實了商業對象程序包的各種不同的類的設計。接口更加精確,選擇了屬性的數據類型。
系統的當前版本不必檢查一本書是否及時歸還,也不必處理預借書籍的訂單,因此Loan和 Reservation類的日期屬性就沒有實現。
雜志和書的處理過程是完全相同的,除了借期的不同,而且它還不用處理。 在分析中, Magazine和 Book Title子類已經被認為不必要的並且在 Title類中只有一個類型屬性指定該書名是否指出一本書或雜志。在以後的應用程序版本中,如果認為有必要的話,這兩個簡化都可以刪除。
分析過程中的狀態圖表在設計階段又被細化了,顯示在工作系統中狀態如何被表示以及被處理。 Title類的設計狀態圖表如圖 6。 其他對象可以通過調用 addReservation ( )和 removeReservation ( )操作來改變 Title的狀態,就像這張圖表中所顯示的那樣。
圖6解釋 設計Title的狀態圖
用戶界面包 用戶界面包總是在其他包之前,在系統中,它給用戶提供服務和信息,顯然,這個包基於標准的 Java AWT ( Abstract Window Toolkit )類。設計模型中的動態模型已經被分配到 GUI包中,因為所有的與用戶的交互作用都是通過用戶界面開始的, 此外,我們還選擇序列圖表來說明動態模型,本使用案例的設計模型的實現都是用細節描述的,包括類中的實際的操作。序列圖表實際上是以一系列迭代的形式創建的。在實現(即編碼)階段更多的細節上的發掘會產生更進一步的迭代。 圖 7表明 Add Title的結果設計序列圖表。
圖7解釋 Add Title的序列圖
我們還可以使用協作圖表代替序列圖表,象圖 8。
圖8解釋 Add Title的協作圖。
第三節 用戶界面設計
在設計階段,我們使用一個特定活動創建用戶界面。
圖書館應用程序中的用戶界面是基於本使用案例的,並且已經被分成下列部分,在主窗口上,它的每個部分都已經被給予一個單獨的菜單欄:
1、功能 本系統中的主要功能的窗口就是用來借書、還書以及與借書籍的登記工作等。
2、信息 本系統中的查看信息的窗口就是用來收集書名和借書者的信息。
3、維護 維護本系統的窗口用來添加、更新和刪除書名、借書者以及書籍。
圖9 是一個用戶界面包中的類圖的例子。
圖9解釋 功能類圖模型。
一般情況下,每個窗口提供一個系統中的服務並且映射到一個使用案例 (即使並不是所有的用戶界面都必須從一個使用案例中映射而來), 創建一個成功的用戶界面超出本文討論的范圍,讀者朋友請參閱文後提供的代碼。我以後還會專門輯文探討這個問題。
實現
程序設計在構造或實現階段就開始了,應用程序的要求規定本系統能夠運行於各種不同的處理器和操作系統,因此Java語言是實現本系統的最好的選擇。Java可以很容易的映射邏輯類到代碼組件,因為一個類有到Java代碼文件的一對一的映射。圖 10說明了在本例中的設計模型的組件圖表包含一個邏輯視圖中的類到組件視圖的組件的簡單映射。每個組件包含一個邏輯視圖中的類的描述的鏈接,這樣就使在不同的視圖之間定位變得很容易 (即使,象在本例中,它只是簡單的使用了文件名 )。組件之間的依賴在組件圖表中並沒有表示出來(除了商業對象包 ),因為可以從邏輯視圖中的類圖衍生出它們之間的依賴。
圖10
為了編碼,要從設計模型中的下列圖表中取得規范:
類規范: 每個類的規范,用於詳細地說明必要的屬性和操作。
類圖: 它所要介紹的類的類圖,說明了它的靜態結構和與其他類的相互關系。
狀態圖: 類的狀態圖,說明了可能的狀態以及需要被處理的過渡期 (以及觸發該過渡期的操作 )。
類的對象中包含的動態圖 (序列圖、協作圖以及活動圖):說明類的一個具體的方法的實現的圖表或者是說明其他對象是如何使用類的對象的圖表。
使用案例圖表以及規范: 等開發者需要知道關於系統使用情況時說明系統被使用的結果(當開發者覺得被整個系統的細節問題所搞糊塗的時候)。
顯然,設計階段的不足將在編碼階段暴露出來,我們需要找出哪些操作需要更新、哪些操作需要修改,這就意味著開發者將不得不改變設計模型。 在所有個項目開發中都會遇到這種事情, 重要的是,我們要使設計模型和代碼同步,這樣設計模型就能被稱為系統最後的所需要的設計。
考慮下面這些要點:
Java程序包規范是規定這個類所屬的組件或邏輯視圖的等價代碼。
私有屬性符合模型中規定屬性的。 並且, Java方法符合模型中的操作。
ObjId類 (對象標識符)被調用來實現關聯,這意味著關聯通常被和該類一起保存 (因為 ObjId類是持久的類)。