OOA&D實踐之路——真實案例解析OO理論與實踐(一)
一、導言
為什麼要寫這個系列
“OO都是一個已經被討論爛的話題了,還有什麼可寫的!”
不知當你看到文章標題時,是不是有這種疑問,或者鄙夷。不錯,OO從誕生到現在經歷了不短的歲月,與其相關的理論、技術、原則、實踐、模式、語言已經出了一大堆。可是,你真的瞭解OO的本質嗎?真的能揮灑自如的將OO應用於軟體開發中嗎?真的能發揮OO的能量,從而提高軟體質量嗎?如果對這三個問題,你不能很乾脆的點頭說:“是的,當然!”那麼也許你可以抽一點時間,往下看一看。
這個系列文章不打算大篇幅重述各種OO理論,也不打算談各種OO心法。這系列文章著重於通過實踐澄清一些對OO的誤會,幫助朋友們更好的使用正確的方法將OO應用於實際開發中。同時,在必要的地方簡要敘述一下OO相關知識。
所以,這個系列不是關於OO理論的天書或OO參考大全,而是告訴你“你對OO可能存在哪些誤會與認識上的偏差”以及“如何走出誤會更好的OO應用於實踐”。
OO是技術,不是理論
OO,我認為全稱應該叫做“面向物件技術”。其實,OO自誕生那天起其全部目的就是應用於軟體開發實踐中,提高軟體開發質量。這也是OO存在的全部意義。所以,搞OO和搞數論、搞理論物理不一樣,不能脫離應用。搞OO的人應該算是工程師,而不是科學家。兩者最大的區別是:科學家可以不考慮自己研究的成果有沒有什麼應用價值。而工程師不一樣,他們要更“勢利”,要時刻關心自己研究出的東西有什麼應用價值。所以一切OO的研究要以可應用性為嚮導,不能天馬行空誇誇其談。
當然,OO需要理論支撐,但是一定要是有現實意義的理論,而不能像數學家那樣為了理論而研究理論,更不能將已有理論當做教條機械性使用。
因此,在學習和實踐OO的過程中,要時刻注意和應用性聯絡起來,才能避免走入理論OO和教條OO的歧途。
到底什麼是OO
“什麼是OO?”對於這個問題,很難一言以蔽之。但正是由於對這個概念的誤解和偏差,才使得某些朋友一直不能正確使用OO,不能讓OO真正服務於軟體開發,到最後開始懷疑OO、鄙視OO甚至唾棄OO。
在所有對OO的偏差性認識中,最普遍的一點就是“金錘”式理論,即“XX就是OO。”例如,“把所有東西看成物件就是OO”,“遵循封裝、繼承、多型就是OO”,“應用良好的OO原則進行設計就是OO”,“使用UML就是OO”。顯然,這種“一錘子敲定”的方式會讓人割裂的看問題,從而無法從全域性角度正確把握OO。
在這裡,我斗膽給OO下一個定義:OO,即面向物件技術,是一種旨在提高軟體質量的綜合性技術,其貫穿於軟體系統的調研、分析、設計、開發、測試、維護、擴充套件、升級等整個生命週期,它包含一系列概念、思想、理論、目標、原則、實踐、模式、工具、語言等要素,這些要素既相互區別又相互聯絡,同時從巨集觀和微觀兩個角度共同協作,指導和引導開發人員開發出高質量軟體,並指導與開發有關的一切過程。
從上面可以看出,OO並不是孤立的概念或技術,而是一系列要素的複合體,並貫穿於整個軟體開發週期。所以,僅僅從某個時間或控制元件切面切入而應用OO,這樣的OO是不完整的,也不可能發揮出其應有的作用。打個比方:如果使用OO的方法和工具進行分析、設計,但是編碼過程不能做到OO,就好比製造了一輛豪華的轎車卻找頭驢拉著走,是不能提高你出行效率的。反過來,如果你是一個C#或Java高手,但分析設計過程不遵循OO,直到編碼時才用C#或Java試圖OO,這無異於你聽說開車能提高出行速度,於是你苦學駕駛技術,並掌握了高超的駕駛本領,但最終卻坐在一頭驢子上,於是你開始大喊:駕駛技術是騙人的!根本沒法用!是啊,驢子上連方向盤、離合器都沒有,空有一身駕駛本領又如何發揮出來呢。
這個系列的文章概要和內容組織
這系列文章的大體寫作方式,是通過一個實際案例《XX食品公司連鎖店線上定料系統》的調研、分析、設計、開發等一系列過程,幫助大家更好的認清OO如何實踐,同時澄清一些誤會。這個系統是我曾經參與過的實際案例,為了文章需要,將進行一定程度的修改,但一些很關鍵的東西都會原汁原味保留下來。在整個過程中,請各位不拘泥於具體技術相關問題,而要一直保持一個較高的視端,一睹OO的全貌。
文章的大概組織方式:
第一部分:需求分析之前的故事
很多人認為就軟體開發來說,第一步是需求分析,其實非也。如果想更好實踐OO,需求分析之前還有很多工作,如特性調研、降低風險等環節,這一部分我們講講需求分析之前的故事。
第二部分:分析步步高
這一部分開始對系統進行真正的分析,讓我們來看看OO是如何引導和指導我們分析的。
第三部分:設計的方方面面
設計是一個繁雜的過程,諸多OO原則與模式都會應用於其中,這一部分不會細講各種原則及模式,而是看看正確應用原則與模式的方式是怎麼樣的。
第四部分:讓所有努力開花結果
這一部分,我們將前面的成果付諸實踐。通過這一部分,可以清楚的看到前面做的一切工作都不是飄在雲裡的空中樓閣,而是開發高質量軟體不可缺少的部分。
以上是目前的規劃,當然,在整個過程中可能會出現變化,但是大體條理不會打亂。希望本系列文章能給您帶來幫助。
二、第一項任務:特性列表
第一份說明
當這個專案開始時,我們得到的關於我們要做的系統的唯一說明是一頁Word文件,這是一份簡單的不能再簡單的說明。文件裡只有一行字:我們需要一個系統,使得全國各地的代理加盟商和連鎖店能夠通過網路訂購原料。另外,我們還知道這是一個食品公司,主營麵包、麻花、肉夾饃等食品,在全國各地有多家連鎖機構。除此之外,我們一無所知。
永遠不要和客戶談需求
軟體開發的第一步是什麼?很多人覺得是需求分析。顯然這短短的一句說明無法滿足我們的要求,於是很自然的,你希望找客戶談話,詳細瞭解情況,然後做出詳細的需求分析。於是,你心裡有了這麼一個算盤:
和客戶談話 -> 問清所有需求 -> 進行需求分析 -> 生成需求文件
乍看之下,這是很合理的步驟,但是實際上這是不可行的。原因有如下幾點。
1.客戶不關心繫統的所有方面
每個開發人員都希望,客戶可以清楚的把自己需要的東西的方方面面清楚無誤告訴你,然而,這只是一廂情願罷了。因為,任何一個客戶在需要什麼東西的時候,只會大致想想要個什麼東西,並不會將所有地方都仔細想清楚。
2.有時客戶並不清楚自己到底要什麼東西
有時候,客戶並不是很清楚自己想要什麼。這不是天方夜譚。很多時候,客戶僅僅有一個“想要實現某個目的的動機”,而沒有“我需要一個什麼系統”這麼明確的概念。例如,從上文那個“一句話說明”中,可以看出,我們的客戶僅僅是有一個動機:希望有一個系統,能使得他們公司的代理商和加盟店線上定料,至於這是一個什麼樣的系統,他們並沒有明確的概念,更不用說這個系統有什麼樣具體的需求了。
基於以上兩點,你是不可能從客戶那裡問清所有需求的。實際上,就不該和客戶談需求,因為需求從來就不是“客戶面”的東西,而是“開發人員面”的東西。需求需要包含方方面面系統需要實現的功能,而客戶往往並沒有如此精細想過,甚至客戶自己對自己想要的東西什麼樣子都不清晰。面對這種客戶,你一本正經往他面前一坐,開發筆記本說:“我們談談需求吧”,或說“我們進行需求分析吧”,我想客戶會立馬崩潰,而你也不可能得到你想要的所有東西。
作為開發人員,不應該一開始就和客戶談需求,而要先談特性。很多需求並不需要客戶告訴你,開發人員應該能通過常識識別出來,就如沒有哪一個買汽車的客戶會說:我需要一個輛汽車,要有方向盤,還要有四個輪子。他們通常會說:“我要一輛家用車、要省油、舒適,要至少能坐3個人。”這“家用車”、“至少能坐三個人”就是特性。
特性是一些描述,一條特性簡要描述了系統的一個客戶最關心的核心功能。
最為開發人員,首要任務不是做需求分析,而是幫助使用者整理出一份特性列表。這裡之所以說“幫助”,是因為很多時候,客戶由於自身太關注於某個方面,而漏掉了十分重要的特性,這是你要幫客戶想想,並將想到的特性詢問客戶是否是需要的。如果客戶很高興的說“對!對!”,那麼這就是大功一件。所以,在初期階段,開發人員一定要想客戶之所想,急客戶之所急,儘快幫客戶理清系統有什麼特性。
所以,正確的過程應該是:
詢問客戶系統都有什麼功能 -> 寫出初期特性列表 -> 想想什麼遺漏特性,並詢問客戶 -> 查漏補缺
生成特性列表
下面回到案例。
雖然客戶的說明只有一句話,我們還是整理出一份初期的特性列表,並將其作為我們向客戶展示的第一份工作成果。這份特性列表內容如下:
1.可以將各種原料資訊釋出到系統上
2.加盟商和連鎖店可以通過系統線上定料
沒錯,我們的初期文件只有兩項特性。我們把這個給客戶看,客戶說:“嗯……大約是這個東西吧。”很顯然,我們的客戶是比較懶的那種,這時,我們有義務引導客戶想起更多需要的特性。下面是當時大約對話:
開發人員(簡稱D),客戶(簡稱C)
D:你這個加盟商和連鎖店是要如何區分呢?
C:我們公司有一個加盟商和連鎖店的記錄。
D:那麼你們是準備將各個加盟商的資訊全部錄入系統嗎?
C:不是,我希望他們能自己註冊,就和論壇那種。
D:那麼你要如何確認他們的身份,總不能任何人都可以在這個系統註冊吧。
C:嗯,我們公司有各個加盟商的詳細資訊,我們希望他們註冊時提供足夠的資訊,我們進行核對。
(於是我們飛快寫下一個特性:加盟商和連鎖店通過網路進行註冊,總店負責人稽核後才可以正式使用系統。)
D:你們得在後臺能釋出各種原料的資訊吧。
C:嗯,使得。
D:這裡有沒有什麼特別的要求。
C:沒有吧……
D:好的,那麼你們準備設立幾個人負責管理這個系統。
C:就一個人吧,就資訊部那個。我們就這一個比較懂計算機的。
D:也就是說不需要有多個人分別管理這個系統?
C:不需要。
(寫下一個特性:系統需要一個管理員,可以對系統進行管理)
D:在你們的加盟商進行定料時,你希望他們怎麼操作啊。
C:這個,我沒仔細想過……
(看客戶對這個地方比較不清晰,我們打開了一個網上書店的網站,給他演示了一下購物車購物的過程)
D:你看,你的這個定料過程是不是和這個購物過程很相似,加盟商定料是不是就相當於從總公司購買原料啊。
C:對對!就要這種效果的!
(這裡要記住,在特性不能直接說清楚時,找相似事物是一個不錯的選擇。也就是說,說明這個特性像什麼,不像什麼)
(我們又加一條特性:使用購物車功能進行網上定料)
D:付錢這一塊怎麼弄,需要網上支付嗎?
C:不了,我們一般又財務專門做錢這一塊工作。
D:那買完原料後要不要什麼憑證呢?
C:買完後生成一份定料單吧,打印出來,交給財務,財務清算款項,款到賬後通知原料那邊發貨。
(又一條特性:定料完成後生成定料單,並可以列印)
D:那麼關於這些交易,你一定希望能查詢吧,你希望怎麼查詢。
C:哦,這些我們財務那邊有專門的財務軟體。你這個系統只要能讓加盟商定料就行了。
到這裡談話基本結束,我們得到如下一張補充過的特性列表:
1.可以將各種原料資訊釋出到系統上
2.加盟商和連鎖店可以通過系統線上定料
3.加盟商和連鎖店通過網路進行註冊,總店負責人稽核後才可以正式使用系統
4.系統需要一個管理員,可以對系統進行管理
5.使用購物車功能進行網上定料
6.定料完成後生成定料單,並可以列印
我們將補充後的特性列表給客戶看了看,基本得到了認可。
到了這裡,我們第一步就差不多做完了。但是,我們還是不能馬上進入需求分析,因為這之前還有很多事情要做。例如,特性整理,風險規避,這都是後面要討論的話題。
重點總結
1.客戶不會想到方方面面。
2.有時客戶並不明確自己想要什麼東西,而僅僅是有個動機。
3.不要和客戶談需求,要談特性。
4.開發人員有義務引導和幫助客戶挖掘系統的特性。
5.當客戶描述不清某個特性時,可以採用找類似事物的方法,說說這個特性像什麼,不像什麼。
6.在軟體開發初期,我們需要首先整理出一張特性列表,而不是做需求分析。
三、降低風險
風險無處不在
在上一篇文章中,我們寫出了一張特性列表。然後是不是就可以做需求分析了?很遺憾,還不可以,我們仍有許多工作要做。拿到特性列表後第一件事,就是要儘量降低風險。這裡先不長篇大論風險如何如何,我們先做,從做的過程中體會降低風險的涵義。
DRY
這裡,首先要引入一個OO原則——DRY。
DRY原則,全稱Don't Repeat Yourself,指:在系統中,每一個資訊或行為片段應該僅僅存在一份,且存在於合適的地方。
對於這個原則,很多朋友將其理解為“不要出現重複的程式碼”,這是很片面的理解。其實,OO本身並不是僅僅關於如何寫出優秀的程式碼,而是關於如何開發出優秀的軟體。所以,很多OO原則並不是僅僅程式碼層面的原則,而是可以應用於整個開發過程的。下面來著重看看這個原則的深層意義,以及討論其在降低風險中的應用。
如何利用DRY降低風險
在所有的開發風險中,有一種風險,是由於同一個資訊或行為片段分散於系統的不同地方,從而導致重複勞動,並且給修改和維護造成隱患。
下面,分別通過例子來描述兩種不良後果。
1.重複勞動
例如,在特性列表中,如果兩個特性本身應該是一個特性,但被誤認為是兩個不同特性。那麼所有基於特性的分析和設計都存在重複勞動,即對同一個特性,做了兩遍分析和設計,直到發現重複為止。這個代價是巨大的。
2.修改和維護隱患
例如某一程式碼段完全相似,但是出現在程式的諸多地方。這些相似的程式碼段一定是完成完全相同的功能,於是有著“同生同滅”的特點,即如果某段程式碼要修改,一般來說所有這段程式碼的重複程式碼都要修改。這就給維護帶來很大隱患。
DRY原則正是針對這種風險的一個解決方案。關於DRY在程式碼中的應用,暫且放下,這裡只看它在特性列表整理中的應用。顯然,根據DRY原則,要求特性列表中的特性不能具有重複,那麼我們再仔細看看我們的特性列表:
1.可以將各種原料資訊釋出到系統上
2.加盟商和連鎖店可以通過系統線上定料
3.加盟商和連鎖店通過網路進行註冊,總店負責人稽核後才可以正式使用系統
4.系統需要一個管理員,可以對系統進行管理
5.使用購物車功能進行網上定料
6.定料完成後生成定料單,並可以列印
仔細檢查,不難發現2和5其實是在描述一個特性,於是我們將2和5合併成一個新的特性:加盟商和連鎖店可以使用購物車功能線上定料。另外,可以看出,“總店負責人”和“管理員”其實是一個概念。整理完後,得到如下新特性列表:
1.可以將各種原料資訊釋出到系統上
2.加盟商和連鎖店可以使用購物車功能線上定料
3.加盟商和連鎖店通過網路進行註冊,管理員稽核後才可以正式使用系統
4.系統需要一個管理員,可以對系統進行管理
5.定料完成後生成定料單,並可以列印
再仔細檢查,已經沒有重複特性。這樣,我們就應用DRY原則規避了第一種風險:重複勞動的風險。下面給這種風險下一個定義:
重複勞動風險——指由於重複特性的存在,導致對同一特性進行了一遍以上的分析設計過程。最終導致資源浪費,開發效率降低,可能導致無法按時交付。
知之為知之 不知為不知
在使用DRY整理完特性列表後,下一步就是要規避第二種風險:概念模糊。
概念模糊風險——指由於開發人員對於某一領域知識不熟悉,而將某一個概念想當然,繼而根據這個想當然的結果進行分析設計。如果其想法錯誤,則會導致系統無法正常使用或無法完成業務既定目的,從而導致返工或專案失敗。
很明顯,一般來說開發人員並不是業務專家。所以對於領域業務不熟悉是很正常的,作為一個合格開發人員,應該謹遵孔老夫子“知之為知之,不知為不知”這一教誨,謹慎負責對待不熟悉的概念,而不能從字面臆想。正確的做法是,首先審視特性列表,對於不熟悉或拿不準的概念,去請教領域專家或客戶。下面繼續以我們的專案為例。
經過對特性列表的分析,我們找出以下疑問或模糊概念:
1.原料(都是什麼原料,需要分類麼?)
2.加盟商和連鎖店(兩者有什麼區別?定料業務流程一樣麼?)
帶著著兩個疑問,我們再次拜訪了客戶。具體交談就不說了,最後我們得到了如下結果。
1.原料主要就是些炸粉、調料之類的配方需要保密的烹飪原料,沒有太特別的,不需分類。
2.加盟商和連鎖店不是一個概念,加盟商直屬總公司,連鎖店可能直屬總公司也可能直屬某加盟商。加盟商和直屬總公司的連鎖店直接向總公司定料,不直屬的的連鎖店向相應加盟商領取原料。連鎖店按原價定料,加盟商按照等級分為5級,每級折扣不同。
經過以上一番瞭解,我們基本把模糊概念搞清楚了,並且經過這麼一瞭解,我們的特性列表隨之改變:
1.可以將各種原料資訊釋出到系統上
2.加盟商和連鎖店可以使用購物車功能線上定料
3.加盟商和連鎖店通過網路進行註冊,管理員稽核後才可以正式使用系統
4.系統需要一個管理員,可以對系統進行管理
5.定料完成後生成定料單,並可以列印
6.直屬連鎖店按原價定料,加盟商按照等級分為5級,每級折扣不同
我們認為加盟商級別和折扣是很重要的特性,於是把它加到了特性列表裡。
保證我們能夠實現
上面我們已經避免了兩種風險。現在再來看一種風險。舉個例子,如果一個建築設計師,設計了一座新型別墅,其中有一條特性是:院子裡有一個季節調節裝置,可以隨意將院子裡的季節調節為春夏秋冬中任意一個季節。你們認為這個特性怎麼樣?很酷的創意對不對?但是如果你是別墅的客戶,你會這麼想?我想你不會和設計師一起為這個非常酷的特性而激動,你會首先問設計師要怎麼實現這個功能。沒錯,可以調節季節的院子是很棒,可以不要忘了,最終我們的別墅是要建築在實際中的,而實際總會有諸多約束不能讓每一個想法變成現實。
同上。無論我們設計的東西多麼天花亂墜,最終都是要編碼實現的。所以,我們要保證所有的特性可以在編碼層級上有解決方案。即使我們不能馬上知道精確的解決方案,但也要大體知道怎麼實現。由此引出了第三種風險:
實現能力風險——指由於某項特性不能由具體技術解決帶來的風險。這種風險包括兩個層面,第一是現有技術完全解決不了。第二是由於開發團隊沒有解決方案。這種風險可能導致專案延期甚至失敗。
要規避這種風險,就要逐一審查我們的特性是否可以在現有技術範圍內解決。仔細審查後,第一個層面應該是沒有問題,所有這6種特性都可以在現有技術內解決。但是對於特性2,我們存在一定問題。因為當時我們都沒有設計購物車的經驗,一下子不知購物車是如何實現的。
為了解決這個問題,要做如下工作。這裡要注意,我們在這裡可能討論了很多細節,但是我們要避擴音前進入細節。所以,這裡討論的所有細節並不是要進行分析或設計,而僅僅是通過頭腦風暴的方式大約有個譜。這個“譜”往往和最終的實現有很大不同,但是至少我們知道這個特性通過某種方式可以實現。
在遇到這種風險時,首先要做的是查詢相關資料。在查找了一些資料後,我們瞭解到購物車一般分為Session實現方式和資料庫實現方式。這兩種方式特點不同,前者支援未登入購物,確不能儲存客戶購物資訊。而後一種又必須登入後才能購物。這裡涉及到客戶的利益,所以要由客戶決定。
於是,我們詢問了客戶,得到的答覆是“未登入時要可以定料,而且也要保持定料資訊。”這句話有點模糊,但大體可以知道客戶的意思,於是我們改寫成如下一段話“未登入的使用者可以使用購物車,但不能下定料單,登入後才可下單。登入使用者可以保持購物車中資訊。”我們拿給客戶看,並進行了一定描述,客戶認同了這個決策。
這個確定後,我們就要討論一下具體解決方案了。我在這裡再次說明,以下的討論不是分析或設計,而僅僅是讓我們對棘手的問題更清晰一些,從而心裡有個譜,避免實現的時候不知如何是好。
在經過一番討論後,我們都同意的解決方案是“未登入的使用者使用Session處理購物車,登入的使用資料庫儲存購物資訊。當用戶登入時,如果Session中有將購物資訊,將Session中的資訊轉入資料庫。”
這個討論可以到此為止了。因為我們不需要太精確,我們只要大致心裡有個譜就行了。
重點總結
1.特性列表完成後,我們首先應該降低風險,而不是做分析或設計。
2.重複特性存在風險。可以用DRY原則處理。
3.存在模糊不清概念的特性存在風險。請仔細詢問客戶,不要想當然。
4.不知如何實現的特性存在風險。一定要保證對每條特性的實現方式心裡大致有個譜,但不需很精確。
四、通覽全域性:避免過早陷入細節的泥沼
細節的泥沼
現在我們再次將特性列表貼過來:
1.可以將各種原料資訊釋出到系統上
2.加盟商和連鎖店可以使用購物車功能線上定料
3.加盟商和連鎖店通過網路進行註冊,管理員稽核後才可以正式使用系統
4.系統需要一個管理員,可以對系統進行管理
5.定料完成後生成定料單,並可以列印
6.直屬連鎖店按原價定料,加盟商按照等級分為5級,每級折扣不同
我們已經和這則列表折騰很久了,相信很多朋友已經厭倦了,肯定在想:不要在折騰這該死的特性列表了,趕快開始吧。這點我同意。但是要開始做什麼?很多朋友可能會說:開始用例分析吧。說實話,用例是好東西,它讓我們清晰認識到系統的工作流程,正式因為過於清晰,所以很容易讓我們陷入一個細節的泥沼。
應該說,從“特性列表”直接到“用例分析”不是一個好注意,因為特性列表關注於功能(Function),而用例關注於系統的業務流(Business Flow),我們從功能直接開始分析系統的細節業務流,這個跨越太大,不利於軟體質量的保證。特性是相對分散獨立的功能描述,而用例是系統細節,很明顯,在這之間應該有一個過渡,而這個過渡,就是一個高層次的,從全域性角度對系統的一個概觀認識。這個概觀認識起到承上啟下的作用,既將特性列表對映為一個系統的大概模型,又給系統細節的分析奠定了基礎。所以,在系統特性基本確定後,我們首先要從全域性給出一個系統的概覽,避免落入用例分析這樣細節的泥沼。
概覽系統的有力工具——用例圖
既然我們要給出一個全域性的系統概覽,自然就需要有一種方式將其表達出來。顯然,僅僅通過說是不理想的,我們需要一種能用於書面表達的工具,而這個工具,就是我們非常熟悉的UML圖之一的用例圖。
很多朋友可能有疑問,上面不是說不進行用例分析嗎?怎麼這裡又畫用例圖了?因為用例和用例圖表述的資訊層面完全不同,用例更傾向於細節和業務流的描述,而用例圖傾向於整體的描述。下面給出兩種工具要表述的資訊:
用例——表述某個互動操作的動作執行者、用例名稱、具體流程過程、例外情況等。
用例圖——表述系統有哪些執行者、有哪些用例以及執行者於用例、用例於用例之間的關係。
很明顯,用例更關注於某一個操作的具體流程,所以適合在需求分析中使用;而用例圖更關注於整個系統的使用和互動情況,因此能給我們一個系統的概覽。
下面,我們就使用用例圖,從高層次角度看看系統的樣子。在這裡還要說明的是,隨著UML和用例分析技術的發展,提出了業務用例和系統用例的區別,而且用例存在不同的粒度。在進行高層次概覽的時候,我們是使用的是一種粒度比較粗的用例圖。也許在以後的需求分析中,我們還會使用粒度更細的用例圖。
通過簡要對特性列表的分析,可以畫出一張如下的用例圖:
可以看到,這個用例圖並沒有太多細節的東西,而僅僅描述了三個資訊:1.系統有哪些使用者 2.系統有哪些操作 3.系統和使用者有哪些互動。這些,就是我們要的一個系統概觀。
用例圖的驗證
畫完用例圖,我們並不是就完事了。因為,要使得用例圖真的是全域性概觀,就一定要保證一點:圖中用例覆蓋了所有特性。如果不能覆蓋所有特性,說明我們的用例圖中缺少用例甚至缺少動作執行者。現在我們來驗證一下:
特性1覆蓋於“原料管理”。
特性2覆蓋於“線上定料”。
特性3覆蓋於“註冊”和“加盟商和連鎖店管理”。
特性4覆蓋於“原料管理”和“加盟商和連鎖店管理”。
特性5覆蓋於“列印定料單”。
特性6覆蓋於...???
我們忽然發現一點,這裡並沒有和折扣有關的東西,那麼這個特性沒有被用例覆蓋。我們知道,如果要實現這個特性,系統中一定要有一定的折扣機制,而一定是有管理員設定的。於是我們增加一個“折扣管理”用例。注意,這裡我們可以先不陷入細節,僅僅知道系統有這麼一個折扣機制,至於具體怎麼實現,到分析設計階段再討論。於是,修改後的用例圖如下:
現在我們可以說:特性6覆蓋於“折扣管理”和“線上定料”。
好了,這樣我們已經確認,用例圖的用例覆蓋所有特性。
重點總結
1.不要過早陷入細節
2.在特性列表到用例分析之間,用該先有一個系統概覽,讓我們從高層次上審視系統全貌。
3.用例圖是實現這種概覽的有效方式。
4.用例不要粒度過細,要能反應系統粗粒度操作。
5.最後不要忘了檢查圖中用例是否覆蓋了所有特性。