<form id="dlljd"></form>
        <address id="dlljd"><address id="dlljd"><listing id="dlljd"></listing></address></address>

        <em id="dlljd"><form id="dlljd"></form></em>

          <address id="dlljd"></address>
            <noframes id="dlljd">

              聯系我們 - 廣告服務 - 聯系電話:
              您的當前位置: > 關注 > > 正文

              軟件開發中的“OO”到底是什么?真實案例解析OO理論與實踐

              來源:CSDN 時間:2023-01-28 14:06:26

              一、導言

              為什么要寫這個系列


              (資料圖片僅供參考)

              “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實現方式和數據庫實現方式。這兩種方式特點不同,前者支持未登錄購物,確不能保存客戶購物信息。而后一種又必須登錄后才能購物。這里涉及到客戶的利益,所以要由客戶決定。

              于是,我們詢問了客戶,得到的答復是“未登錄時要可以定料,而且也要保持定料信息?!边@句話有點模糊,但大體可以知道客戶的意思,于是我們改寫成如下一段話“未登錄的用戶可以使用購物車,但不能下定料單,登錄后才可下單。登錄用戶可以保持購物車中信息?!蔽覀兡媒o客戶看,并進行了一定描述,客戶認同了這個決策。

              這個確定后,我們就要討論一下具體解決方案了。我在這里再次說明,以下的討論不是分析或設計,而僅僅是讓我們對棘手的問題更清晰一些,從而心里有個譜,避免實現的時候不知如何是好。

              在經過一番討論后,我們都同意的解決方案是“未登錄的用戶使用Session處理購物車,登錄的使用數據庫存儲購物信息。當用戶登錄時,如果Session中有將購物信息,將Session中的信息轉入數據庫?!?/p>

              這個討論可以到此為止了。因為我們不需要太精確,我們只要大致心里有個譜就行了。

              重點總結1.特性列表完成后,我們首先應該降低風險,而不是做分析或設計。       2.重復特性存在風險。可以用DRY原則處理。       3.存在模糊不清概念的特性存在風險。請仔細詢問客戶,不要想當然。       4.不知如何實現的特性存在風險。一定要保證對每條特性的實現方式心里大致有個譜,但不需很精確。

              四、通覽全局:避免過早陷入細節的泥沼

              細節的泥沼

              現在我們再次將特性列表貼過來:       1.可以將各種原料信息發布到系統上       2.加盟商和連鎖店可以使用購物車功能在線定料       3.加盟商和連鎖店通過網絡進行注冊,管理員審核后才可以正式使用系統       4.系統需要一個管理員,可以對系統進行管理       5.定料完成后生成定料單,并可以打印       6.直屬連鎖店按原價定料,加盟商按照等級分為5級,每級折扣不同

              我們已經和這則列表折騰很久了,相信很多朋友已經厭倦了,肯定在想:不要在折騰這該死的特性列表了,趕快開始吧。這點我同意。但是要開始做什么?很多朋友可能會說:開始用例分析吧。說實話,用例是好東西,它讓我們清晰認識到系統的工作流程,正式因為過于清晰,所以很容易讓我們陷入一個細節的泥沼。

              應該說,從“特性列表”直接到“用例分析”不是一個好注意,因為特性列表關注于功能(Function),而用例關注于系統的業務流(Business Flow),我們從功能直接開始分析系統的細節業務流,這個跨越太大,不利于軟件質量的保證。特性是相對分散獨立的功能描述,而用例是系統細節,很明顯,在這之間應該有一個過渡,而這個過渡,就是一個高層次的,從全局角度對系統的一個概觀認識。這個概觀認識起到承上啟下的作用,既將特性列表映射為一個系統的大概模型,又給系統細節的分析奠定了基礎。所以,在系統特性基本確定后,我們首先要從全局給出一個系統的概覽,避免落入用例分析這樣細節的泥沼。

              概覽系統的有力工具——用例圖

              既然我們要給出一個全局的系統概覽,自然就需要有一種方式將其表達出來。顯然,僅僅通過說是不理想的,我們需要一種能用于書面表達的工具,而這個工具,就是我們非常熟悉的UML圖之一的用例圖。

              很多朋友可能有疑問,上面不是說不進行用例分析嗎?怎么這里又畫用例圖了?因為用例和用例圖表述的信息層面完全不同,用例更傾向于細節和業務流的描述,而用例圖傾向于整體的描述。下面給出兩種工具要表述的信息:

              用例——表述某個交互操作的動作執行者、用例名稱、具體流程過程、例外情況等。

              用例圖——表述系統有哪些執行者、有哪些用例以及執行者于用例、用例于用例之間的關系。

              很明顯,用例更關注于某一個操作的具體流程,所以適合在需求分析中使用;而用例圖更關注于整個系統的使用和交互情況,因此能給我們一個系統的概覽。

              下面,我們就使用用例圖,從高層次角度看看系統的樣子。在這里還要說明的是,隨著UML和用例分析技術的發展,提出了業務用例和系統用例的區別,而且用例存在不同的粒度。在進行高層次概覽的時候,我們是使用的是一種粒度比較粗的用例圖。也許在以后的需求分析中,我們還會使用粒度更細的用例圖。

              通過簡要對特性列表的分析,可以畫出一張如下的用例圖:

              可以看到,這個用例圖并沒有太多細節的東西,而僅僅描述了三個信息:1.系統有哪些用戶 2.系統有哪些操作 3.系統和用戶有哪些交互。這些,就是我們要的一個系統概觀。

              用例圖的驗證

              畫完用例圖,我們并不是就完事了。因為,要使得用例圖真的是全局概觀,就一定要保證一點:圖中用例覆蓋了所有特性。如果不能覆蓋所有特性,說明我們的用例圖中缺少用例甚至缺少動作執行者?,F在我們來驗證一下:       特性1覆蓋于“原料管理”。       特性2覆蓋于“在線定料”。       特性3覆蓋于“注冊”和“加盟商和連鎖店管理”。       特性4覆蓋于“原料管理”和“加盟商和連鎖店管理”。       特性5覆蓋于“打印定料單”。       特性6覆蓋于...???

              我們忽然發現一點,這里并沒有和折扣有關的東西,那么這個特性沒有被用例覆蓋。我們知道,如果要實現這個特性,系統中一定要有一定的折扣機制,而一定是有管理員設置的。于是我們增加一個“折扣管理”用例。注意,這里我們可以先不陷入細節,僅僅知道系統有這么一個折扣機制,至于具體怎么實現,到分析設計階段再討論。于是,修改后的用例圖如下:

              現在我們可以說:特性6覆蓋于“折扣管理”和“在線定料”。

              好了,這樣我們已經確認,用例圖的用例覆蓋所有特性。

              重點總結 1.不要過早陷入細節       2.在特性列表到用例分析之間,用該先有一個系統概覽,讓我們從高層次上審視系統全貌。       3.用例圖是實現這種概覽的有效方式。       4.用例不要粒度過細,要能反應系統粗粒度操作。       5.最后不要忘了檢查圖中用例是否覆蓋了所有特性。

              五、需求分析之前的故事

              高質量軟件的第一要素

              到目前為止,我們做了很多工作,但是我一直在強調這些都還不是需求分析。在很多人心目中,軟件開發的第一件事就是先做需求分析。那么我們為什么不這樣做呢?這牽扯到一個關鍵的問題:我們都希望開發高質量的軟件,而本系列文章的重點也是如何通過OO實踐開發高質量軟件,那么什么是高質量軟件?

              對于這個問題,也許很多人會說,是靈活的、是易于修改和擴展的、是可維護性高的、是用戶體驗好的、是文檔完整的、是代碼規范的、是性能處理優秀的……好吧,我承認,這些都是高質量軟件必不可少的元素,但是,還有一個更重要的要素,就是:軟件必須做客戶希望它做的事。你的軟件再靈活、編碼再規范,客戶不關心,客戶最關心的是軟件是不是完成了他期待的功能,可以做他希望軟件做的事。所以,高質量軟件的第一要素就是:讓軟件做客戶希望它做的事。

              知道了這點,就知道為什么第一步不是做需求分析了,因為需求分析的重點不是“讓軟件做客戶希望它做的事”,而是“將需求分解歸納成開發人員容易進行領域分析和設計的信息片段”。所以,需求分析是開發人員面的東西,而不是客戶面的東西。作為開發人員,我們要首先站在客戶的角度看問題,而不能總是站在開發人員角度,和客戶隔著一條河對話。我們要走過去,去河的另一岸。

              回顧我們的工作

              現在來總結一下我們目前所做的工作,你會發現,我們所做的全部工作,其目的就是讓軟件做客戶希望它做的事。

              我們首先總結出特性列表,然后通過分析和詢問降低了風險,同時修改了特性列表,最后從做出一張用例圖,使得從全局角度對系統進行一個概覽。所有這一切,其實都是開發人員在“努力變成客戶”,或說努力讓自己站在客戶的角度看系統,真正了解客戶想讓希望做什么。因為,最好的理解需求的方式就是理解客戶想讓系統做什么。

              我們在哪里?看看地圖吧

              做了這么多工作,是不是有點迷失方向的感覺?似乎我們已經迷失在OO從林中,不知現在身在何處。好的,那我們看看“OO地圖”吧,一方面搞清楚我們在什么地方,另一方面看看我們后續有哪些路要走。

              以上就是實踐中的大致開發流程。一般來說,開發大致分為兩個階段:前一階段我們要站在用戶角度,搞清用戶想要系統做什么;后一階段要回到開發人員角度,進行分析、設計、編碼、測試等一系列操作。而我們現在正處在兩個階段的交界處。

              一般在迭代階段提倡使用迭代與增量的方式進行開發。至于這樣有什么好處,以及OO如何于迭代增量方式結合這些問題,我們將在下一篇文章中結合我們的案例詳細討論。

              重點總結1.高質量軟件的第一要素是:軟件做客戶希望它做的事。       2.在開發初期,我們要盡量站在客戶角度。       3.理解需求的最好方法是明白客戶希望軟件做什么。       4.開發流程大約分為兩個階段:搞清用戶想要系統做什么和迭代開發。

              六、迭代式開發與用例驅動

              再次明晰開發流程

              在上一篇文章“五、需求分析之前的故事”中,我給出了一幅開發流程圖:

              這幅圖,加上前幾篇文章的內容,給不少朋友留下諸多困惑。如“特性列表不算需求分析嗎?”、“用例圖怎么跑到需求分析前面去了?沒有需求分析哪來的用例圖?”為了解開這些困惑,我們應該先把開發流程各個相關概念給明確了。

              在一般開發流程中,直觀上可以分為兩個部分:業務階段和系統階段。明確這一點非常重要。其中業務階段主要進行的工作是與計算機無關的,而系統階段才是和計算機相關的東西。上圖中“我們在這里”那道豎線所指的地方,就是業務階段和系統階段的分界點。

              而如果從建模角度分析,整個開發流程分為四個子流程:       a)業務建模流程       b)系統建模流程       c)分析設計建模流程       d)部署實施建模流程       其中a)屬于業務階段,而b)c)d)均屬于系統階段。

              業務建模流程的任務就是做業務分析、降低風險和給出系統總體概覽模型。系統建模主要就是需求工程。分析設計建模就是我們熟悉的概要設計和詳細設計。而部署實施建模是對系統的具體實施建立模型。

              其中,我們一般所說的“需求”,實際是指“系統需求”,是在b)階段進行的,所以a)階段的一切工作,都不能算是需求分析。(當然,如果加一個前綴,說是“業務需求分析”,也是可以的,但是一般在軟件工程領域,說“需求分析”是特指“系統需求分析”。)

              而關于用例圖的疑惑,大家應該知道,用例圖分為業務用例圖和系統用例圖,而業務用例圖產生于a)流程,這樣它們當然會出現在b)流程,也就是需求分析之前。當然,在b)流程中還會出現用例圖,這時就是系統用例圖了。

              明白了以上開發流程,我想很多疑惑就自然解開了。所以,其實我們所謂的“需求分析之前的故事”,就是業務建模流程。

              系統階段的法寶1:迭代與增量

              在上文中,我們提到軟件過程大體分為業務階段是系統階段。在前面幾篇文章中,我們已經基本完成業務階段,下面是進入系統階段了。不過莫急,在正式進入系統階段之前,我們有幾個重要的、關于系統階段的話題要聊一下。

              如果你問我,在系統階段最應該被牢記的是什么,我會告訴你,是兩個詞:迭代&增量。

              我們已經知道,系統階段是在業務階段的基礎上,在計算機領域內進行需求分析、系統分析、概要設計、詳細設計、編碼、測試、部署實施等一系列環節。但是,如果你想僅施行一遍這個流程,而完成整個系統的話,不好意思,你大致會精神崩潰。

              如果這個過程僅實施一遍,其實就成了瀑布模型。小系統也許可以,但是稍大點的系統,將會帶來嚴重的后果。我們知道,“軟件開發中永遠不變的就是變化”,如果采用瀑布模型,反饋將會非??亢螅恢币讲渴饘嵤╇A段才能看到成果,如果客戶要求更改需求或認為當前系統不是他們想要的,那么修改過程會異常慘烈,代價也是巨大的。

              那么,我們應該如何實施系統階段開發呢?法寶就是迭代和增量。具體做法是:

              我們將整個系統分為許多相對獨立的“單元”,每次只對一個或少數幾個單元實施需求分析、系統分析、概要設計、詳細設計、編碼、測試、部署實施等一系列過程,一次這樣的過程叫做一次迭代,而將一次迭代的成果加入現有成果的過程就叫做增量。

              這種開發流程的優勢是明顯的:我們總是能在相對較短的時間內,完成整個系統功能的一個“子集”,這個子集是可以運行的,可以看到效果,所以如果用戶不滿意,反饋是及時的,修改代價也較小。通過合理的過程控制,變更代價總可以控制在一個可以接受的范圍內。

              在實施迭代&增量過程時,要注意一下兩點:

              1)迭代單元不是環節,而是系統功能的某個子集。如不能說第一次迭代完成需求分析、第二次迭代完成設計……這不叫迭代式開發,這叫里程碑式開發,和迭代有本質區別。

              2)每次迭代一定要完整完成需求分析、系統分析、概要設計、詳細設計、編碼、測試、部署實施這一套環節,產生的成果必須是成品,是可運行、可交付的,是整個系統的一個子集,而不能是一個半成品。

              系統階段的法寶2:用例驅動

              相信,大家或多或少聽說過“用例驅動”。那么什么是用例驅動呢?如果你理解了上文的迭代&增量過程,就很好理解用例驅動了。上文不是說過,迭代時每次選取一個或少數幾個“單元”嗎?那么這個“單元”是什么?理論上,什么都可以,只要是對系統合理的劃分。但在實踐中,人們發現,使用業務用例作為迭代單元是最合適的。為什么呢?       其一,業務用例大小適中,規模平均。       其二,業務用例大多相互獨立性好,適合進行迭代。       其三,業務用例能很好反映系統的功能單元。

              所以,所謂的用例驅動就是以業務用例作為迭代單元進行迭代開發的流程。

              你看,我們前面做了那么多業務分析,其中成果之一就是業務用例圖。而這里,業務用例成了我們進行系統迭代開發的單元和驅動者,所以,軟件開發過程不是割裂的,而是相互聯系的,不會說上一個階段過去就過去了,和下一階段毫無聯系。一般,上一階段的產品總會成為下一階段的材料。

              在這里附上一副我自己畫的示意圖,希望能幫助大家理解本文內容:

              本文理論講得多了點,有點枯燥,但是必須講,因為明白這些是以后進行系統階段的基礎。從下一篇開始,我們回歸示例,進入真正的系統階段了。下一篇,將開始第一輪迭代的起始階段:需求分析。

              重點總結 1.軟件過程大致可分為業務階段和系統階段。       2.業務階段進行業務建模流程,與計算機領域無關;系統階段進行系統建模、分析設計建模和部署建模階段,與計算機相關。       3.系統階段的兩大法寶:迭代式開發與用例驅動。

              七、【第一輪迭代】需求分析與領域分析

              在前面,我們花了六篇文章的篇幅去討論需求分析之前發生的事情,這些內容看起來枯燥或飄渺,但實際是為真正開始系統的分析、設計和實現進行的必要準備。從這篇開始,將正式進入系統的開發階段。這一篇文章,將討論第一輪迭代過程中的需求分析和領域分析環節。

              選取第一輪迭代要實現的特性

              回顧前面章節,我們說到,“迭代與增量”和“用例驅動”是系統開發的兩大法寶。另外,指出了如下幾個要點:

              1)迭代單元不是環節,而是系統功能的某個子集。如不能說第一次迭代完成需求分析、第二次迭代完成設計……這不叫迭代式開發,這叫里程碑式開發,和迭代有本質區別。

              2)每次迭代一定要完整完成需求分析、系統分析、概要設計、詳細設計、編碼、測試、部署實施這一套環節,產生的成果必須是成品,是可運行、可交付的,是整個系統的一個子集,而不能是一個半成品。

              所以,說白了,這第一步就是要從前面得到的特性列表或業務用例分析文檔中選取一個或幾個特性或業務用例進行實現。(因為特性和業務用例有對等映射關系,所以,從特性列表或業務用例分析文檔中選取迭代功能點在理論上是等價的。)這里,我們從特性列表選取特性。那么首先把我們前面完成的特性列表再搬出來:

              上圖就是我們前面得出的特性列表,總共有六個特性。理論上,第一輪選取哪些,總共選取幾個,沒有明確的規定,但是,在選取特性方面,還是有一定經驗可以遵循的,大致有如下原則:

              1)就選取個數來說,與迭代周期有關。一般的迭代開發中,一個迭代周期大多選在一周到兩周之間,不宜多于兩周,所以,每個周期選擇的特性要估算能在這個周期內完成。(順便說一下,在每個周期內,如果發現時間不夠,做不完計劃,應削減一些特性推入下個周期,切不可延長周期。另外,切不可在周期開始后添加任務。)

              2)就選取的特性來說,最好是比較內聚的幾個特性。也就是說,每個周期選取的特性,要盡量關聯緊密,而和其他周期的特性要盡量耦合度低。

              3)就選取順序來說,因為要求每一個周期都要產生一個可運行的子集系統,所以,最好先選取平臺性、基礎性、對外依賴弱的特性,再選取功能性、對外依賴強的特性。例如,在這個例子中,如果第一輪迭代選擇特性2則不是一個好主意。因為購物車功能要依賴于管理員、加盟商、物料等諸多特性,在后者沒有實現之前,很難單獨做出一個可運行的購物車子集系統。

              針對以上原則進行考慮,筆者最終選擇3、4和6作為第一輪迭代的特性。

              至于為什么這樣選,我就不再分析,請各位結合我上面提到的三個原則自己思考一下。

              領域分析

              在確定迭代特性后,下一步要進行領域分析。領域分析就是針對特性涉及到的實體及實體間的關系進行一個分析,構造出靜態領域模型。這里要注意三點:1、領域模型是靜態模型;2、領域模型要反映的是實體及實體見得靜態關系(例如包含等,而調用這類動態關系不該在這里出現);3、領域模型是比較高視角的模型,其中的實體和最終程序中的實體類未必對應。

              領域分析的方法有很多,下面我使用一種我總結的領域分析方法。流程如下:

              step1、提取特性中的名詞

              我們這個迭代周期內涉及的特性是3、4和6,從中可提取出如下名詞:加盟商,連鎖店,網絡,管理員,系統,直屬連鎖店,原價,等級,折扣。注意,這些名詞就是領域實體的候選者。

              step2、篩選名詞,確定實體

              不是所有候選名詞都是領域中的實體,這一步要對候選者進行篩選。這一步非常重要,也相對難度較高,需要結合經驗和前面的客戶談論材料、需求記錄等,必要時,要咨詢客戶或業務專家。下面我們進行篩選。

              首先,“網絡”顯然不是領域內的實體,排除?!跋到y”是對整個產品的總稱,也比較明顯不是領域實體,排除。排除了兩個明顯的“干擾項”,下面看幾個可疑的家伙,這里,我發現“原價”、“等級”和“折扣”比較可疑。通過對前面材料的回顧分析,基本可以肯定“原價”應為物料的一個屬性,難以成為單獨的實體,排除。而“折扣”和“等級”是否能成為實體,依賴于后續系統的設計方式,如果將等級單獨設計成一個模塊,則其應該為一個實體,而若將其設計為加盟商的屬性,則不能成為實體。對于這種摸棱兩可的候選項,我們姑且保留,并加一個“?”作為后綴。當然,由于前面分析中說明“折扣關聯與等級”,所以,僅保留“等級”就可以了,“折扣”可作為其屬性。

              經過上述篩選,獲得下列領域實體:加盟商,連鎖店,管理員,直屬連鎖店,等級?。

              我們不妨先將各個實體畫入領域分析圖。

              step3、確定實體間的關系

              有了實體,下面要確定各個實體間的關系。如上圖所示,管理員比較容易確定,因為它似乎不與任何實體存在靜態關系。這里比較糾結的是加盟商、連鎖店、直屬連鎖店和等級四個實體。關于它們間的關系我們不能臆想,要去查閱前面的記錄資料或去咨詢客戶。在OOA&D實踐之路——真實案例解析OO理論與實踐(三、降低風險)一文中,我們記錄了這樣一段文字:

              “加盟商和連鎖店不是一個概念,加盟商直屬總公司,連鎖店可能直屬總公司也可能直屬某加盟商。加盟商和直屬總公司的連鎖店直接向總公司定料,不直屬的的連鎖店向相應加盟商領取原料。連鎖店按原價定料,加盟商按照等級分為5級,每級折扣不同?!?/p>

              從以上文字中,我們提煉出如下關系:

              1)加盟商和連鎖店沒有關系。

              2)直屬連鎖店是連鎖店的一種特例。而且應該還有種“非直屬連鎖店”

              3)非直屬連鎖店可能會屬于某個加盟商。

              4)等級僅屬于加盟商。

              到這里為止,幾個實體間的關系基本清晰了,我們將其表達在領域分析圖里:

              以上就是第一輪迭代的領域分析圖了。其中直屬連鎖店和非直屬連鎖店都繼承于連鎖店,而非直屬連鎖店必定對應一個加盟商,加盟商可以對應零到多個非直屬連鎖店,每個加盟商有且只有一個對應的等級。

              step4、領域分析的優化

              別覺得完成上述步驟就萬事大吉了,雖然我們的領域分析模型已經出來了,但它可靠嗎?還有優化的余地嗎?萬事多思考一點,總是沒壞處的。就像剛出廠沒經過檢測的飛機,你敢坐嗎?所以,這里我們要對已經成型的領域分析模型進行一個檢測。檢測的方法很簡單,就是回顧前述工作,逐個點進行驗證和確認。當我回顧了特性及初步業務需求后,發現如下兩點問題:

              第一、管理員是否是領域中的實體?要知道,領域中的實體,一定是系統邊界內的實體。那這里就要分情況討論了,如果系統只需要一個管理員,那么系統中就沒有對管理員的管理,那么管理員只是系統外部的用戶,就不能存在于領域實體中了;如果有多個管理員,并且管理員管理單獨成為一個模塊,則管理員應放在這里。于是我聯系了客戶,在確認系統只需要一個管理員后,我毫不猶豫將管理員從領域模型中抹去了。

              第二、我覺得領域模型抽象層次還有所欠缺。加盟商和連鎖店性質很類似,都有注冊、都要被審核,其實它們應該繼承自某個更高抽象,這里我稱其為會員。于是經過思考和修正,得到最終的領域模型如下:

              這里要注意,領域模型只表示出實體和實體間的靜態關系就好了。至于各個實體有哪些屬性,有哪些交互,那是后面設計階段的工作。

              基于用例的需求分析——編寫用例圖及用例規約

              傳統的軟件工程中,通常使用需求規格說明書進行系統需求分析。而我更喜歡使用用例分析技術。在用例分析階段,我們要輸出兩份文檔:用例圖和用例規約。用例圖用于概觀上描述需求,用例規約用于對用例的流程進行詳細描述,直接作為后續設計、編碼及測試的依據。

              下面進行系統需求分析。

              step1、提取特性中的動詞

              上面我們曾使用提取名詞法找實體,那么要找用例,就要分析特性中的動詞了。廢話不多說,我們先提取出特性3、4和6中的動詞:注冊,審核,使用,管理,定料。因為用例分析中要確定每個用例的Actor,所以,在提取完動詞后,要對每個動詞賦予其主語,作為其Actor,于是,最終得到的提取列表如下:注冊【未注冊加盟商和連鎖店】,審核【管理員】,使用【注冊后的加盟商和連鎖店】,管理【管理員】,定料【注冊后的加盟商和連鎖店】。

              step2、動詞篩選

              同樣的,不是每個動詞都是合法的用例,這里也要對候選動詞進行篩選。具體到這里,“使用”是個很泛的名詞,不應該成為用例,而“定料”雖是用例,但于這輪迭代的內聚性不高,建議放入后續迭代中。最后得到用例:注冊【未注冊加盟商和連鎖店】,審核【管理員】,管理【管理員】 。

              step3、用例分析與優化

              這里的用例有進一步分析的余地,首先,“管理”這個用例粒度太大,很難知道設計和開發,于是應進行分解;其次,“審核”應屬于管理的一部分?;谝陨蟽牲c,將管理分解為“刪除會員”、“指定加盟商等級”和“審核會員”,另外,“未注冊的加盟商和連鎖店”,跟據領域分析,可寫作“未注冊會員”。另外,這里有幾個隱含的用例,就是關于等級的管理,這幾個用例從動詞分析中是提取不出來了,這取決于特性描述的局限性。我們通過經驗和個人的分析,得到關于等級的管理用例。于是,最終用例敲定如下(這里用例命名規則為 uc迭代周期編號.用例編號):

              uc1.1 - 注冊 actor:未注冊會員

              uc1.2 - 刪除會員 actor:管理員

              uc1.3 - 指定加盟商等級 actor:管理員

              uc1.4 - 審核會員 actor:管理員

              uc1.5 - 添加等級 actor:管理員

              uc1.6 - 刪除等級 actor:管理員

              uc1.7 - 等級信息維護 actor:管理員

              step4、給出用例圖

              跟據上述分析,給出用例圖如下:

              step4、編寫用例規約

              需求分析的最后一步,就是為每個用例編寫相應的用例規約。用例規約是一種規范化文檔,它面向設計開發人員,詳細描述了各個用例內部的基本信息、執行流程及例外流程等,必要時可附上相應的活動圖。因為用例規約是設計和開發的重要參考文檔,所以在編寫過程中務必要做到詳盡和準確。

              下面僅給出“注冊”這個用例的用例規約作為示例和參考。

              必要時,可在下端附上活動圖:

              總結

              在每個迭代周期的初始階段,當選擇完需要迭代的特性后,就可以開始領域分析和需求分析了。本文是先進行領域分析。其實兩者并無確定的先后順序,往往是相輔相成,交叉進行。下一篇文章將進入第一迭代周期的設計階段。

              作者:T2噬菌體 出處:http://leoo2sk.cnblogs.com

              本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。

              責任編輯:

              標簽:

              相關推薦:

              精彩放送:

              新聞聚焦
              Top 中文字幕在线观看亚洲日韩