需求分析與系統設計的面向對象推導過程
幾年前寫的了,這兩天整理東西的時候又給翻出來了,當時是公司讓給我給設計人員講講如何寫面向對象的設計說明書,所以臨時東拼西湊的弄了這么個東西,畢竟是用于內部培訓的,有些東西都是直接從網上整段COPY的,最多就是用自己的話又修飾了一遍,在此說明一下,各位看到的時候,莫過多糾結于此 。
一. 引言
1.1 文檔概要
概要很簡單...
1.2 編寫目的
解釋設計說明書里應該寫些什么,在寫設計說明書之前應該給我什么,寫完了設計說明書應該達到什么樣的效果,或者換個說法,寫完了設計說明書我能給代碼開發人員什么。
1.3 背景
背景很復雜
1.4 定義
類型 |
名稱 |
定義 |
縮寫詞 |
RUP |
Rational Unified Process,統一軟件開發過程,由IBM提出的基于面向對象且適應于大型項目的程序開發方法論 |
OO |
Object Oriented,面向對象 |
|
XP |
Extreme Programming極限編程 。一種認為輕量的軟件開發方法論,強調架構,文檔不如直接編程來得直接。適應于小型項目的開發實踐 |
|
專門術語 |
||
1.5 預期的讀者和讀者建議
讀者類型 |
備注(建議) |
項目經理 |
了解從需求到設計的全過程 |
需求分析人員
|
了解從需求到設計的全過程,著重看需求分析部分 |
系統設計人員
|
了解從需求到設計的全過程,著重看系統設計部分 |
開發人員 |
著重看系統設計推導部分對于各種圖例以及相關說明表的解釋。理解這些圖例及相關的說明表的具體意義,目的是能看懂概要設計說明書里的內容。對于推導的過程則只須大致了解即可 |
二.參考文獻
《系統分析與設計》 JohnW.Satzinger Robert B.Jackson Stephen D.Burd 著朱群雄 汪曉勇 等譯 機械工業出版社
《大型軟件體系結構:使用UML實踐指南》[美]Jeff Garland Richard Anthony著 葉俊民汪望珠 等譯 電子工業出版社
《設計模式精粹》[美]Alan Shalloway & James R.Trott 著熊節 譯 清華大學出版社
《編寫有效用例》[美]Alistair Cock Brun 著 機械工業出版社
《用例分析技術(原書第二版)》機械工業出版社
《OO系統分析員之路--用例分析系列》 coffeewoo
《RUP文檔模型》
#p#
三.內容
3.1 需求分析
雖說本文檔是為設計說明書的編寫進行服務。但我覺得如果要想明白設計階段能夠做些什么,就得知道前一階段能夠給我輸入些什么,設計的前一階段是需求。所以我們得搞明白需求能給我們輸入些什么。當然要想搞明白需求能給我們輸入些什么。就又得搞明白需求的最終文檔是怎么一步一步分析出來的。要不然直接給我們一堆文字外加一堆UML圖。我們也搞不明白究竟是些什么東西。所以本文檔有必要從需求分析開始入手,一步一步推導到概要設計說明。詳細設計本文檔不作考慮。
本文檔采用的是面向對象的推導過程。而非面向過程的推導過程。所以在開始推導之前先給大家測一下,看看你到底是面向對象的潮流人群呢,還是面向過程的遺老遺少。
如果你的分析習慣是在調研需求時最先弄清楚有多少業務流程,先畫出業務流程圖,然后順藤摸瓜,找出業務流程中每一步驟的參與部門或崗位,弄清楚在這一步參與者所做的事情和填寫表單的結果,并關心用戶是如何把這份表單傳給到下一個環節的。那么很不幸,你還在干著面向過程的事情。
如果你的分析習慣是在調研需求時最先弄清楚有多少部門,多少崗位,然后找到每一個崗位的業務代表,問他們類似的問題:你平時都做什么?這件事是誰交辦的?做完了你需要通知或傳達給誰?做這件事情時你都需要填寫些什么表格?....那么恭喜你,你已經跟上了時代的潮流,進入了OO人群的行列!
當然是OO的先不要忙著得意,前路漫漫,還有的你走。是遺老遺少的也不用忙著灰心,改進為時不晚。
本文檔主要采用了RUP(統一軟件開發過程)的思想。而非XP(極限編程)的思想。采用RUP并不是說RUP就比XP好。這兩個本身就無所謂誰好誰壞,因為在適應的對象上兩者是完全不同的。對于中小型公司和中小型軟件來說,XP是非常有效的管理方法,它能大大降低管理、開發成本和技術風險。不過要是對于大公司和大型項目來說,XP就不適用了,這時RUP卻表現的非常出色。你能想象波音公司用XP的方法來開發747是一個什么情形嗎?先不要管飛機將來是什么樣子,反正先造一架出來,出問題了,摔了找找原因,改進改進,重構一下,再造一架....再摔了,沒關系,咱們不怕變更,再造就是了。如果真是這樣,恐怕波音公司早掛了。那XP什么情況下適用呢?如果你是一個雜貨店的老板,不知道什么樣的商品受歡迎,沒關系,我們可以先各進一小批貨,賣上一段時間,然后看顧客的反應,受歡迎的貨品我們就多進一些,不受歡迎的嘛就少進一些或者不進,順便再和顧客多多交流一下,直接問問他們喜歡什么,不喜歡什么。不斷的改進,不斷的完善。我想最后一定會顧客盈門的。但是假如這時這個老板非得先進行一下什么市場調研,再做個什么商業方案,順便再搞搞風險評估,最后再進行下客戶關系研究,消費曲線分析。猛一點的,再加上個消費心理問卷....估計還沒開業,就破產了。
在本文檔中采用RUP的過程僅僅是因為他更全面,更嚴謹一些。另外對于一些面向對象里的基礎理論,無論是對于RUP還是XP都還是適用的。在我看來 RUP 與 XP 的區別不在技術,僅在對于過程中對精細程度的把握尺度與迭代方式的不同而已。
注:使用的RUP的推導與分析和迭代過程,文檔并不一定采用RUP。
本文檔主要講的是推導過程,故對過程中的細節不作深入的描述。例如如何獲取“有效的”用例以及獲取用例時,所要考慮到的市場因素和風險因素,以及在需求分析和系統設計時的相關管理事項(例如需求會議召開,怎樣與客戶交流,進度的控制,成本)等不作進一步描述。相關內容可自行參考有關書籍和論文。
最后再啰嗦一句:我本身對于面向對象的理解也不是很深刻,因時間緊迫,還有很多東西未完全吃透,故錯誤肯定是在所難免的。如果不怕被誤導那么你可以放心大膽的往下看了,如果怕誤導,還是勸你就此打住比較合適。
下面我們正式開始推導過程。
- 尋找執行者與設計用例
RUP是一種用例驅動的迭代開發過程。那么何為用例驅動呢?這個很好理解,看字面就能猜個八九分,就是一切從用例開始,然后一步一步推導出我們想要的結果。那么用例又是什么呢?這是我們提出來的第一問題
什么是用例 ???
我們先不忙著做出解答。先假設一段場景,AA公司是一家轉購公司,他們從不同的供貨商那里進貨后,然后再賣出去。最近他們想讓我們去為他們開發一套系統,我們接到任務后給他們公司打了一個電話,他們為我們安排了一位銷售經理進行電話交流。我們把這次交流的結果整理后,得到了如下的一段描述
目前隨著網絡的普及,很多的上班族趨向于采用使用網絡這種做在家里就可以購物的方式。所以我們公司準備開發一個網上的訂單平臺。客戶可以 通過網絡查看我們發布的產品并選購,然后通過銀行或者其它付款方式付款給我們,我們則通過快遞公司或者其它方式將產品直接送到客戶填寫的寄送地址。客戶可以退貨。并要求重新進貨。當然可能需要額外的支付一筆費用。
看到這樣一段描述,你可能覺得大致清楚要做的是什么樣的東西了,但對于構建一個系統來說,這樣的描述還差太多的東西,其中有很多的細節并沒有表述出來。然而不幸的事,往往在前期你也就只能從客戶那里挖出來這些東西了,尤其是你在調研時僅僅只和一個崗位的相關人員進行了交流。當然也許你的客戶夠專業,你們的交流使你獲得了比這多的多的消息, 但無論如何, 你的經驗會告訴你:你第一次獲得的東西永遠都不可能是完備的,你也永遠不要奢望第一次就能講全部的需求都搞到手。
那么獲得了這樣一段并不完備的描述后,我們應該做些什么呢?繼續追問?NO,能獲得這樣的需求在目前看來我們已經做的足夠好了。 自己去完善客戶的需求并交付開發人員去開發?NO,要知道使用系統的是客戶而不是你。也許你可以為客戶設計一套流程,或者一個訂單的樣式,但那可能并不是客戶所需要的,假如你認為客戶不大會授權你去為他們在某些方面進行設計,你就千萬不要去自作主張。當然絕大多數客戶都是懶惰的,大部分的情況是他們非常樂于讓我們先幫他們思考,然后他們在我們思考的基礎上給出些意見就行了。是的,這就是我們下面要做的事――分析這段需求,找出這段需求中的隱藏信息,分析出他們要做的這套系統究竟會涉及到哪些人(涉眾),并簡單的為每個涉眾列出你所能想到的他所要做的事情,然后將這些以易于客戶理解的方式告訴他們所有相關的人員,然后她們就會在此基礎上提出她們自己的想法,你記錄下她們的這些想法,對這些想法進行分析后將它們補充到你的需求里,之后再將你這個最新的分析后的需求提交給客戶審查,如此迭代,直到客戶說OK,我要的就是這個東西。
如果你沒有和系統的所有相關者(涉眾)進行過交談,并獲得了有用的信息。永遠不要說你已經做好了需求
下面我們就具體討論一下如何去分析這段需求。此時用例開始登場。當然本文檔講的是一個推導過程,不是一個迭代過程,故在下面的描述中我們不考慮迭代的因素,所有的分析都是假設在一個很順利的環境中進行,這樣也許會讓你覺得條理更清晰一些(包括上面那段不完備的描述在這里我們都假設他已經是很完備的了)。
當然在繼續往下介紹之前,為了更加專注于需求的功能要求,我會回避掉前面提到的一個概念“涉眾”,而改用“執行者”代替。執行者是涉眾的一個子集,涉眾是同你要開發的系統相關的一切人或物,而執行者則是同你要開發的系統直接接觸的一切人或物。從這兩個定義上我們可以看出,涉眾可能不是這個系統的直接操作者,例如一個用于控制機床運作的系統,財務部門可能不會去使用,但因為項目的款項是由財務部支出,所以財務部門是和本系統相關的人或物,所以它是涉眾,但卻不是執行者。
對于執行者的確定過程,本文檔不再作相關的描述,下面只給出此描述里的執行者的相關UML圖形
RUP的所有分析都是從確定執行者開始的。以后的所有分析也都是基于執行者,整個需求的獲取與分析過程都是圍繞著 某某執行者 做了 某某事 進行的。當然這也是面向對象的分析方式,非獨RUP。
確定了執行者,那么下面我們就開始為每個執行者確定其所有的用例,這里已經是第三次提到用例了。當然在這里我還是不會給出他的定義,你目前要做的不是追問這個問題而是繼續的往下看。然后在下面的分析中總結一下自己對用例的理解,并自己給出一個定義或者不斷的修改你的定義。當然在最后。我會在適當的地方給出用例的定義。這時你可以拿它和你的定義進行比較。也許你會發現。其實你的定義比我給出的更加的精確,更加的好。當然,你也可以完全不用去管用例的定義究竟是個什么東西。的確對于用例來說,他的定義并不是必須的。任何的定義恐怕也都是不完備的。
好的, 下面我們讓我們來開始提取用例吧,在提取之前請確保你能夠再次認真的檢查一下執行者,看看是否還有什么遺漏,確定沒有后再動手,當然遺漏總是難免的, 這并不要緊, 我們還可以在后面的用例分析中再將它加進來。你現在只須做到一點即可:即是在用例分析前,你對執行者的確定已經做到了最好,這一點是很重要的。
對于執行者來說,一個用例應該是一個完整的任務。一個用例應該是在一個相對連續的時間內完成。如果有明顯的時間斷層,應該考慮一下把你的用例進行分解。成為多個用例。當然這并不是一定的,這涉及到了用例提取的粒度問題,這個問題相當的復雜,在此不作討論,否則這個文檔真要成為一本書了。不過還是建議你去查查相關的資料,因為這個也很重要。
下面我們給出上面AA公司經理的一段描述的用例圖,這張是經過一次討論后,得出的用例圖,從圖中可以看出來有些東西是在上面的那段描述中不曾出現的,這是討論的結果,其中討論的過程,在此不作敘述,怎么討論也不準備花時間去寫,這些方面的具體內容你可以自己去查看相關資料。
當然這張圖僅僅只是經過一次討論出來的結果,這個用例圖也并不是完善的,其中很多東西并沒有考慮到。例如財務的處理,銀行的轉帳等等都沒有考慮進去。雖然如此,隨時的畫出用例圖卻是非常有必要的,因為任何一個未完成的用例圖都是我們目前分析的成果,我們以后的分析也都以這張圖作為基礎與參考,這樣會使我們更容易發現我們還有哪些方面沒有考慮到,一旦發現了沒有考慮到的事情,就馬上更新這張圖,將你的發現或者想法加進去,當然也要在合適的時間與地點將這張圖拿過去與客戶交流,并告訴他們這是我們目前分析出來的系統需求,有了這張圖客戶可以很容易的明白目前我們已經做了哪些,還有哪些我們沒有考慮進去,這時他就會告訴我們他們的想法。我們再對他的想法加以整理,再一次的更新這張圖。然后重復上述的步驟,直到客戶說OK。
#p#
當然還是為了以后說明的方便,在此文檔中不描述迭代的過程,所以我們假設這種圖已經是最終的用例圖了。
雖然這張用例圖已經可以很清晰的描述了系統與所有相關執行者之間所進行的互動操作。但在實際的分析過程中,只使用這一種圖往往是不夠的,在實際的分析過程中,我們會發現 為每個執行者單獨列出他所涉及的一切用例對于發現執行者還有什么操作沒有加進去是很有用的,另外 為每個用例單獨列出一張相關執行者 對于發現每個用例中還有那些相關人員沒有考慮進去也是非常有用的。同時,對于一些典型的業務場景畫一張業務場景圖對于客戶理解用例以及在發現業務的大體流程上還缺少什么環節也是很有必要的。所以下面我們分別帖出這三種圖。
為每個執行者列出他所涉及的所有用例(以客戶為例,實際操作中你需要為所有執行者列出一張這樣的圖)
為每個用例列出所有相關的執行者(以訂購貨物為例,實際操作中你需要為每個用例列出一張這樣的圖)
業務場景圖(一次交易的場景)
我們在這里第一次接觸到了場景這個概念,在下面我們還會遇到另外一種場景,用例場景。在這里還是不講場景究竟是個什么定義,通過業務場景和用例場景,大家可以自己去比較一下之間的異同,然后自己給出一個定義。在這個場景圖中,橢圓代表的是用例,方格的正式名稱叫泳道,在業務場景中,每個泳道代表一個執行者,在用例場景中,會有所不同。大家注意一下之間的區別,同時大家在看這個場景圖時,是不是發現了有兩個訂購貨物用例,那是因為客戶和業務代表都參與了這個用例。雖然在實際上訂購貨物的過程中,并不一定需要客戶和客戶代表必須在一個連續的時間內完成一系列動作(用例的一種粒度劃分方法),對于傳統的電話訂購方式一個訂購的過程可能會涉及客戶和客戶代表,但在網購當中這種用例設定是不準確的。事實上應當將它一分為二。一個是客戶的訂購貨物用例,一個是客戶代表的審核訂購信息用例,但是本文檔中為了展現用例分析中的更多細節,到目前為止,訂購貨物用例一直被視為電話訂購的情況。但在后面的用例場景分析時,我們將重新將訂購貨物假定為只有客戶一人參與的用例(網購時的情況)。另外從這張圖中,我們可以明顯的看出來許多的不協調,例如,這本身是一宗交易,卻從頭到尾,沒有看到錢的影子,因此看了這張圖后,我們就會考慮是否應該將電子支付系統這個執行者加進去。在實際的分析過程中,這個回答是肯定的,但在這里,我們先不忙著管它。至于原因,后面會給你回答
在進行下面的描述之前,我們將我們的用例圖修正一下,使之更適應于網購
修正后如下:
注意:本圖只是對訂購貨物一處進行了修改,實際上取消定單等地方也應作相應修改,為了節省時間,就先這樣了。當然,如果你修正了用例圖,前面所涉及的一切用例相關的圖形都應作相應的修改。
用例是非常復雜的,僅僅用UML里的一個橢圓來代替,似乎太過簡單了點。所以我們現在有必要引入一張表格――用例描述表對用例進行更加詳盡的文字描述。用例描述表如下(以訂購貨物用例為例,實際中你應為每個用例都填寫這樣一張表格)
用例名稱
|
訂購貨物用例 |
用例描述
|
客戶通過此用例完成對商品的訂購功能 |
執行者
|
客戶 |
前置條件
|
客戶已經打開主頁 |
后置條件
|
返回訂單編號給客戶 |
主過程描述
|
1.當客戶在主頁選擇訂購貨物,用例開始 2.客戶查找目錄,選擇需要訂購的產品 3.對于每個商品 a)系統顯示商口的圖片價格等相關信息 b) 客戶將其加入購物車 c) 系統自動計劃購物車內的商品的價格總和 循環結束 4.客戶選擇購買 5.系統要求用戶輸入用戶名和密碼 6.客戶鍵入用戶名和密碼,并提交 7.系統提示用戶填寫送貨地址等相關信息 8.客戶添寫送貨地址等相關信息,并提交 9.系統提示用戶填寫寄送方式 10. 用戶選擇寄送方式,并提交 11.系統提示用戶選擇支付方式、 12.客戶選擇使用銀行卡支付,并填寫相關信息,提交 13.系統顯示交易訂單,并將其作為未完成的訂單保存,并向電子支付系統要求支付。 14.支付確認后,訂單被標記為確認。并提示用戶交易成功, 用例結束 |
分支過程描述
|
對于每個商品,在a)后選擇放棄,回到2 如果用戶之間已經登錄,在4處直接跳至7 假如客戶選擇使用余額付款,在10處跳至13處 |
異常過程描述
|
如采用余額,用戶余額不足,計算機顯示余額和所需金額 |
業務規則 |
購物車中至少有一個貨物,才能提交。 |
補充說明 |
可以看到在這個用例表中,我們已經詳細的描述了用例的細節與步驟。其中的主過程描述又叫主成功用例場景,每個分支過程則獨自構成一個分支用例場景。同時我們注意一下。主過程描述中的用粗字體表示的那個“電子支付系統”。是不是有點熟悉,在討論業務場景時,曾經提到了他,并且當時并沒有把他加入執行者中去,為的就是在此處說明一個問題,就是在寫用例描述表時,我們也能夠發現一些曾經忽略的執行者或者用例。此時一旦發現,我們同樣必須及時的去更新用例圖。以使你的用例圖更加的完善更加的接近于客戶的要求。
雖然用一堆生澀的詞匯和句子是可以完全的表述一個用例,但是不免讓人覺得有點難以接受。沒有什么太直觀的印象,因此我們有必要再引入一些圖形。以使之形象化。用例場景圖 正好能夠滿足這個要求.每個用例場景圖,對應著一個用例場景(一個用例有多個場景,一個主場景+多個分支場景),在此我們只畫出主用例場景的 用例場景圖,分支場景將不再繪出,各位可自行去繪。
經過了反復的迭代,分析以及與客戶的交流,目前我們已經得到所有的用例以及他的場景,并一一用UML使之圖形化。同時這些用例及場景也已得到了客戶的認可,并被認為已經能夠很好的描述出他們所希望的系統的樣子。那么下面我們可以放心的進入建模的下一個環節――分析業務實體了,當然在進入下一環節之前,我還得履行此節開篇的諾言,給出用例的定義。
用例:還是不做介紹了,可能會誤導。
補充說明:在發現用例,尤其是粒度比較大的用例時,畫出事件表,對于分析有很大的幫助。詳細情況,請自己查看相關的文檔。
#p#
- 設計業務實體
從上一節里,我們繼承了諸多的成果,例如用例,場景以及花了N長時間繪制的那一堆用例圖和場景圖。其中我們需要的是用例描述表和用例場景圖。這兩個可以幫助我們很好的去發現業務實體。
業務實體的命名其實很準確,但是不太容易被程序員所理解。假如我講對象的話可能會讓你感覺更親切一些。但是我們要明白一點。業務實體和對象雖然有著密切的關系,但卻也有著本質的區別。對象確切的說是面向對象編程的一個術語,是和計算機密切相關的,是一個設計階段的概念。而業務實體則仍是一個需求階段的概念,需求文檔是要給客戶看的。所以業務實體不會去考慮抽象,設計模式等。假如你在需求文檔里弄出個什么FACTORY,或者FAÇADE模式。就好比財務人員給你弄出些什么復式記帳法,借貸平衡,借方科目,貸方科目。亦或科技人員給你弄出些什么量子理論,測不準原理。絕一點的哲學家再給你弄出些個什么奧卡姆剃刀,證偽主義一樣。肯定會搞的客戶一頭霧水,不知所云。
業務實體是需求階段的概念,對象是設計階段的概念
要對業務實體進行分析,我們先要從用例描述表和用例場景圖中分析出來究竟有哪些業務實體。這是一項技巧性很強的工作。有些簡單的一眼就能看出來(名詞),有些則隱藏的很深,這需要有相當的經驗和對實體的敏銳感知能力以及認真仔細的態度。這不是本文檔要討論的。本文檔只講到這個步驟你要提取業務實體了就行了。
業務實體一般包括 實實在在的事物、角色、組織部門、設備、交互行為、地點位置等
下面我給出一張業務實體圖(只根據訂購貨物用例簡單的分析了一下,實體不是很全,實際當中,你要把所有的實體都分析出來。本文檔只簡單演示一下而已)
分析出來了有哪些業務實體。下一步就得分析業務實體的關系。圖如下
關系主要有一元(回歸)關系,二元關系,三元關系,N元關系,其中二元關系比較重要。其具體又分一對多,一對一,依賴,多對多等,具體請查閱相關資料。
理出來關系后。下一次我們開始分析業務實體的屬性。所謂屬性就是有關業務實體的一條特定信息。
屬性:有關業務實體的一條特定信息
對于業務實體的屬性在需求分析階段一般不采用UML圖形的方式,而是采用領域模型(業務實體)說明表的形式表示。領域模型說明表如下(以商品為例,實際中應為每個實體寫一份這樣的說明)
實體名稱
|
商品
|
||
實體描述
|
每個商品都經有上架(錄入商品信息),預購(放入購物車),賣出,退貨和下架幾個狀態,詳細請參看商品狀態圖
|
||
屬性名稱
|
類型
|
精度
|
說明(屬性的業務含義及業務規則)
|
商品編號
|
字符
|
12
|
商品類別編號(3位)+商品購入年份(4位)+流水號(5)位 |
商品分類 |
數字 |
3 |
商品的分類 |
名稱 |
字符 |
100 |
商品的名稱 |
價格 |
數字 |
12 |
商品的價格 |
折扣 |
數字 |
6 |
折扣價 |
產地 |
字符 |
100 |
商品產地 |
簡介 |
字符 |
1000 |
商品的內容簡介,上架時錄入 |
狀態
|
字符
|
1
|
商品的狀態,可參看商品狀態圖 |
下面給出說明書表提到的商品狀態圖。
當然并不是每個實體都必須要畫出一個狀態圖,對于那些只有兩三個狀態或者沒有狀態的實體。完全可以不畫狀態圖。但對于有較多狀態的實體,建議還是不要偷懶的好。
好了,萬里長征終于走了一半了。到目前為止,整個需求分析階段算是基本完成了。回顧一下前面的敘述,從提取執行者,到獲得用例,再而根據用例寫出業務場景,再對用例進行詳細的分析從而勾勒出用例場景,最后再到發現業務實體,并理清他們之間的關系,同時對他們的屬性進行挖掘。我們經過了一個從朦朧到初步認識的過程,在這段過程中,我們積累了很多的成果,也學會了畫許多樣的UML圖形,但是一切還是顯得那樣雜亂,還是顯得那樣沒有條理性,現在我急需的是一個文檔,對上面所述的一切進行歸類與整理,以使之更容易被人所明白與理解。這個文檔就是需求說明書。本文檔提供一個需求說明書的例子(此文檔僅作例子,具體需求說明書版式,需采用公司統一標準),見附件1。需求說明書也將作為輸出文檔。輸出到下一個階段--設計階段。當然實際的RUP要輸出的東西更多,具體可參見RUP相關資料。
3.2 系統設計
- 劃分子系統
這一過程理論上是屬于需求分析階段,當用例越積越多時,就已經有必要對用例進行整理與分類,將功能相盡或者相關度較高的用例歸入一個比較大一點的類里,從而形成組件,再繼續歸類,從而形成子系統。當然這一步,也可以放到設計階段來完成。所以將這一部分的內容寫到了這里。如果需求階段已經劃分了子系統,在設計階段直接繼承,如果沒有,則需在設計階段的第一環節劃分出子系統。對此我不準備再作過多的敘述,各位可參考相關的資料。接口也同樣。須各位自行去查考相關的資料,這畢竟只是一個文檔,不是一本書。
要說明的一點是,在需求階段劃分出來的子系統,在設計階段需要再審查一下,進行進一步的優化。優化的過程貫穿于整個設計階段。接口也同樣。這就是跨階段的迭代,當然要盡量避免這種跨階段的迭代。如果你有過多的跨階段迭代,就有必要重新審查一下你的需求分析做的是不是有什么問題了 。
- 設計”類”
類的設計是從分析業務實體(領域模型)開始的。最初的類的設計就是簡單的將需求分析階段分析出來的業務實體用類的形式表現出來。當然業務實體之間的關系,以及業務實體的屬性,也都應一并繼承下來。做完了這些后我們要做的就是分析類的形為,類的形為也叫類的方法,有些書籍上也叫類的責任或者消息。當然現在我們先不著急做這一步,先將上面分析出來的業務實體 轉成類的形式 再講。類圖如下
屬性信息我就不在這里表述出來了,實在是太煩了,時間也緊。
有了這張圖,下面我們開始在他的基礎上分析一下類的形為。分析類的形為的具體方法不在本文檔里進行討論,相關的資料和書籍N多,可以自己去看。
下面僅列出經過簡單分析后重新更新過的類圖,在這個類圖中加入了形為
當然這個類圖并不是完善的,也不一定是合理的,在此僅僅只是用來舉例而已,各位不用太過深究了。在進行類的行為分析時一定要綜合所有的和類有關的用例進行分析。同時記住一個很重要的觀點,就是類只對自己負責。用戶類絕不會去添加商品,因為添加商品不是用戶的責任,而應該是購物車或者訂單的責任。購物車類也絕不會去登錄。因為登錄是用戶的責任。而不是購物車的責任。
不知道你是否還記得在進行用例分析時,用例分析完成后,引入了業務場景和用例場景的概念。使之可以對用例的細節進行分析,同時在分析業務場景和用例場景的同時,又進一步的完善了用例。在類中也一樣。在把類分析出來后,便開始分析他的形為。然后根據形為開始分析他們之間的交互,在分析交互的過程中進一步的去完善你的類。迭代,又是迭代。是的。在RUP中,迭代是無處不在的。
記住,從需求分析繼承過來的類并不是最終的類,需求分析階段主要面向的還是客戶,直接繼承過來的類還僅僅停留在業務的層面上,但在進行設計時我們卻不得不考慮到業務在計算機里的實現問題,因此會對這些類進行調整,優化,擴展,以使之更適應于計算機的實現。這些調整包括運用面向對象的一些特性,例如繼承,重載等對類都行重構。在重構的同時。可能會出現許多與具體業務無關的類,雖說他們和業務沒有什么關系。但在使一個業務在計算機中得以實現時卻是必不可少的。所以這些類你也必須得如實的反應于你更新后的類圖上。當然現在我們還是先不著急去管這些,目前緊要的還是進行類的交互分析。
#p#
在類的交互分析中最常用到的是順序圖和狀態圖。至于交互圖愛畫不畫
一般情況下,一個用例的一個場景必須對應一個順序圖,順序圖是為了表現用例中所涉及的類之間的消息傳遞的過程,這個表述可能讓你有點不明白,換種說法,順序圖就是表現用例中所涉及的類之間的調用順序。其實第一種表述中的消息指的就是類的方法。前面也已經指出過類的方法的表述有很多種,消息,責任,行為。但是無論怎么表述,內容都還是一樣的,只是不同的表述用于不同的語境而已。這個知道即可。
狀態圖和順序圖有所不同,順序圖的主體是用例,而狀態圖的主體是類。狀態圖表現了一個類在其參與的所有用例中的狀態的改變及其觸發條件。狀態圖異常復雜,要想真正的理解恐怕還得你去找相關的資料多多的研究一下。這里不再作說明。、
下面我們延續上面的例子,繪制一張訂購貨物的主場景的順序圖,狀態圖太復雜了,而且前面也沒有列舉其它的用例,所以在這里就不畫了。
訂購貨物主成功場景順序圖
在這張圖中,并沒有畫出查找目錄的相關交互過程。那是因為本文檔在進行業務實體分析時,考慮到只是舉個例子而已,故只簡單的畫了幾個實體,思考的并不是很全面。不小心將商品目錄這個業務實體給丟掉了。但又為了免于唐突,在這里也就沒有把和他相關的交互過程表現出來,要不然突然冒出來一個沒見過的類對象。反而更容易讓人糊涂。雖然這個業務實體很重要,但在這里我就不因為他而去更新之前的相關圖例了。這實在是太費事了。大家知道怎么回事就成了。當然在實際的操作過程中,這種思想可要不得。一旦你發現了這種問題,一定要一直的向上追朔,直到將所有相關的內容和圖例全部更新為止。
當然實際情況下,這張序列圖對于開發人員來說無疑是一個噩夢,這個序列圖所表現的那個用例涉及了過多的間斷性動作,導致了這個序列圖中很多動作都是不連續的,如果用WEB開發的術語來講,就是這個序列圖中包含了過多的請求:在一個頁面只有一個HTTP連接的情況下頁面刷新一次叫一個請求,這樣在實現時就需要技術人員去把這個序列圖分解,然而這個分解過程是很痛苦的,當然這不是開發人員的錯,造成這種情況的原因是從一開始(進行用例分析)的時候我們就沒有遵照前面提到的一條原則—一個用例最好是表示一個不間斷的動作。當然這個問題并不是不可解決的,因為只要將原先的那個龐大的用例進行分解就行了,當然這也并不是說,這條用例就沒有存在的必要了,事實上恰恰相反,這種粗粒度的用例卻是必不可少的,因為粒度過細,就會導致用例膨脹,如果沒有這種粗粒度用例進行歸類的話,會導致非常大的混亂,不易讓人理解。這就產生矛盾了,一方面你說一個用例最好表示一個不間斷的動作,一方面又說大粒度的用例必不可少,^_! 你這不是自己打自己嘴巴嗎?事實也確實該打嘴巴,當然打歸打問題還得解決,解決的方法其實很簡單,只須再引入一些概念即可,即是用例的包含與繼承關系,大用例包含多個小用例,當然包含的原始目的是為了用例的重用,但根據目前我的實際經驗,把一個大用例完全分解成各個小用例,然后大用例包含所有的分解后的小用例,這些小用例可以繼續分解,直到用例是表示一個連續的動作(在WEB中則最有可能的是一次請求,或叫一次會話)為止,也就是說葉子節點上的用例都表示一個連續的動作。繪制序列圖時,也只需繪制葉子節點上的用例即可。當然以上是個人經驗之總結,對不對我也不太清楚,各位仔細掂量,附 用例與用例之間的包含與擴展的原始意義 作為參考
用例與用例之間的包含與擴展的原始意義:包含關系表示一種從屬關系,即子用例是主用例中相對獨立的、必須調用的一部分功能。在用例分析中,我們應當將多個用例都共有的、相對獨立的功能提取出來形成一個子用例,為日后代碼復用提供有力保障。擴展關系表示一個功能是對另一個功能的擴展,即被擴展功能不一定調用擴展功能,但擴展功能是對被擴展功能的加強與延伸。在繪制用例關系時,包含關系應繪制成從主用例指向子用例的虛線箭頭,并標注為“include”,表示主用例包含子用例;擴展關系應繪制成從擴展用例指向被擴展用例的虛線箭頭,并標注為“extend”,表示擴展用例是對被擴展用例的擴展。虛線箭頭在UML中代表的是一種依賴關系,即客戶元素了解供應者,并且供應者的變化會影響到客戶元素(依賴是從客戶元素指向供應者的)。
通過對順序圖和狀態圖的分析,可以讓我們更有效的去完善類的屬性以及它的方法。從而,使我們的設計更加的接近于客戶的要求。但這還遠遠不夠,因為目前我們僅僅是停留在完善的層次上,還不能說是一個優秀的設計。甚至連成功的設計都還算不上。因為到目前為止我們還沒有考慮到復用的問題。
復用大致分為三個層次。從低到高依次為,代碼級復用,組件級復用,服務級復用。
- 代碼級的復用:主要依靠面向對象的特性,如繼承,重載,抽象等。此級別復用的執行者是代碼開發人員。(注:建議用組合來代替繼承)
- 組件級的復用:主要依賴于設計模式,例如FACTORY,FAÇADE,ABSTRACT,FACTORY等。這一層面的復用的執行者一般為設計人員。
- 服務級的復用:這個復用的層次最高,理解也最為困難,如有興趣可自行查看關于SOA以及云計算的相關信息。個人認為這個粒度太粗,把握起來很困難,實際運行時,見機行事。
對于復用的其它相關知識,本文檔就不再做什么深入的討論了,各位也可自行查閱相關的資料,只要記住考慮復用是在已經發現了盡可能完善的類后進行的就可以了。當然這也不一定,如果你的經驗夠豐富,可能不自覺的在設計前期就已經將復用考慮進去了,所以我們還是具體情況具體對待吧,不用搞的那么死。
- 數據庫相關
按著上面所述的步驟,經過一次又一次的迭代,一次又一次的反復。終于興奮的發現,原來我們也可以做出優秀的設計。于是乎我們迫不及待的將這些設計的成果發給了開發人員,并自信的對他們說如果照著這個做,保證能做出來一個優秀的系統。然而事實呢,開發人員拿到我們這些所謂的優秀成果。恐怕除了罵爹罵娘罵你祖宗十八代,其它的什么事也做不了。的確,經過上面的迭代,我們的設計看起來已經非常的優秀了,但事實的情況是:根本無法實現。因為到目前為止我們至少還少考慮了一個極其重要的部分。那就是持久化支持,當然這個名詞聽起來有點玄乎。說白了,就是怎么保存數據。再白一點就是講你的這個設計怎么和數據庫扯上關系(當然你也可以使用其它存儲方法,但這里我們只考慮普遍情況)。
當然這里我也只是講出有這么一個過程。具體怎么映射(扯關系就叫映射),是一個類映射成一張表呢,還是一個類映射成多張表呢,亦或多個類映射成一張表呢。又或者怎么處理有繼承關系的類到數據表的映射等等,諸如此類,請自己查閱相關文檔。當然處理完成后。別忘了畫些ER圖啊什么的,這是必須的。
又經過了一個漫長的發現,分析,改正并不斷迭代的過程。終于,概要設計的所有東西我們都分析出來了,也完善了。什么子系統,組件,接口,類,以及他們之間的交互,包括數據庫都寫的很詳細很清楚并且很明白了,同時又不辭勞苦的用UML工具,將這些所對應的什么子系統圖,組件圖,接口圖,類圖,類順序圖,類狀態圖,甚至類交互圖,包括ER圖也都畫出來了。然而你卻驚奇的發現。當你再次把這些東西發給開發人員,然后告訴他們,你去實現吧的時候,他們仍然罵了你的祖宗十八代。的確,這次你是沒有把數據庫設計給拉下,但如此混亂的一堆東西,恐怕也是沒幾個人能夠接受的吧。所以下面我們有必要象整理分析成果時一樣對設計成果也進行一番整理。這并不是件麻煩的事,有現成的格式讓你套――概要設計說明書。按著概要設計書的目錄,將你之前那一堆毫無章法,東一個西一沱的所謂優秀設計的混亂成果們,分門別類放進去,然后你就可以將這個概念設計說明書放心的傳到下一個環節,順利的結束這段折磨人的旅途了。當然如果下一環節是詳細設計說明書的話,恐怕還得逮著你。但一般情況下,詳細設計說明書的情況不多,一般都是直接到開發人員哪里去了。
結語:正如開篇所言,推導過程不是一個一成不變的東西,以上的東西僅供參考而已。
開發軟件不是生產產品,當然開發軟件也不是搞藝術設計,確切的講,應該是介于這兩者之間的東西。鼓勵創意的同時又約束部分的形為、需要流程而又不局限于流程。這就是軟件設計:一個世界上最差勁的藝術設計,外加一個世界上最糟糕的生產過程
原文鏈接:http://www.cnblogs.com/jivi/archive/2013/03/13/2954737.html