一区二区三区电影_国产伦精品一区二区三区视频免费_亚洲欧美国产精品va在线观看_国产精品一二三四

聯(lián)系我們 - 廣告服務(wù) - 聯(lián)系電話:
您的當(dāng)前位置: > 關(guān)注 > > 正文

軟件開(kāi)發(fā)中的“OO”到底是什么?真實(shí)案例解析OO理論與實(shí)踐

來(lái)源:CSDN 時(shí)間:2023-01-28 14:06:26

一、導(dǎo)言

為什么要寫(xiě)這個(gè)系列


(資料圖片僅供參考)

“OO都是一個(gè)已經(jīng)被討論爛的話題了,還有什么可寫(xiě)的!”

不知當(dāng)你看到文章標(biāo)題時(shí),是不是有這種疑問(wèn),或者鄙夷。不錯(cuò),OO從誕生到現(xiàn)在經(jīng)歷了不短的歲月,與其相關(guān)的理論、技術(shù)、原則、實(shí)踐、模式、語(yǔ)言已經(jīng)出了一大堆。可是,你真的了解OO的本質(zhì)嗎?真的能揮灑自如的將OO應(yīng)用于軟件開(kāi)發(fā)中嗎?真的能發(fā)揮OO的能量,從而提高軟件質(zhì)量嗎?如果對(duì)這三個(gè)問(wèn)題,你不能很干脆的點(diǎn)頭說(shuō):“是的,當(dāng)然!”那么也許你可以抽一點(diǎn)時(shí)間,往下看一看。

這個(gè)系列文章不打算大篇幅重述各種OO理論,也不打算談各種OO心法。這系列文章著重于通過(guò)實(shí)踐澄清一些對(duì)OO的誤會(huì),幫助朋友們更好的使用正確的方法將OO應(yīng)用于實(shí)際開(kāi)發(fā)中。同時(shí),在必要的地方簡(jiǎn)要敘述一下OO相關(guān)知識(shí)。

所以,這個(gè)系列不是關(guān)于OO理論的天書(shū)或OO參考大全,而是告訴你“你對(duì)OO可能存在哪些誤會(huì)與認(rèn)識(shí)上的偏差”以及“如何走出誤會(huì)更好的OO應(yīng)用于實(shí)踐”。

OO是技術(shù),不是理論

OO,我認(rèn)為全稱(chēng)應(yīng)該叫做“面向?qū)ο蠹夹g(shù)”。其實(shí),OO自誕生那天起其全部目的就是應(yīng)用于軟件開(kāi)發(fā)實(shí)踐中,提高軟件開(kāi)發(fā)質(zhì)量。這也是OO存在的全部意義。所以,搞OO和搞數(shù)論、搞理論物理不一樣,不能脫離應(yīng)用。搞OO的人應(yīng)該算是工程師,而不是科學(xué)家。兩者最大的區(qū)別是:科學(xué)家可以不考慮自己研究的成果有沒(méi)有什么應(yīng)用價(jià)值。而工程師不一樣,他們要更“勢(shì)利”,要時(shí)刻關(guān)心自己研究出的東西有什么應(yīng)用價(jià)值。所以一切OO的研究要以可應(yīng)用性為向?qū)В荒芴祚R行空夸夸其談。

當(dāng)然,OO需要理論支撐,但是一定要是有現(xiàn)實(shí)意義的理論,而不能像數(shù)學(xué)家那樣為了理論而研究理論,更不能將已有理論當(dāng)做教條機(jī)械性使用。

因此,在學(xué)習(xí)和實(shí)踐OO的過(guò)程中,要時(shí)刻注意和應(yīng)用性聯(lián)系起來(lái),才能避免走入理論OO和教條OO的歧途。

到底什么是OO

“什么是OO?”對(duì)于這個(gè)問(wèn)題,很難一言以蔽之。但正是由于對(duì)這個(gè)概念的誤解和偏差,才使得某些朋友一直不能正確使用OO,不能讓OO真正服務(wù)于軟件開(kāi)發(fā),到最后開(kāi)始懷疑OO、鄙視OO甚至唾棄OO。

在所有對(duì)OO的偏差性認(rèn)識(shí)中,最普遍的一點(diǎn)就是“金錘”式理論,即“XX就是OO。”例如,“把所有東西看成對(duì)象就是OO”,“遵循封裝、繼承、多態(tài)就是OO”,“應(yīng)用良好的OO原則進(jìn)行設(shè)計(jì)就是OO”,“使用UML就是OO”。顯然,這種“一錘子敲定”的方式會(huì)讓人割裂的看問(wèn)題,從而無(wú)法從全局角度正確把握OO。

在這里,我斗膽給OO下一個(gè)定義:OO,即面向?qū)ο蠹夹g(shù),是一種旨在提高軟件質(zhì)量的綜合性技術(shù),其貫穿于軟件系統(tǒng)的調(diào)研、分析、設(shè)計(jì)、開(kāi)發(fā)、測(cè)試、維護(hù)、擴(kuò)展、升級(jí)等整個(gè)生命周期,它包含一系列概念、思想、理論、目標(biāo)、原則、實(shí)踐、模式、工具、語(yǔ)言等要素,這些要素既相互區(qū)別又相互聯(lián)系,同時(shí)從宏觀和微觀兩個(gè)角度共同協(xié)作,指導(dǎo)和引導(dǎo)開(kāi)發(fā)人員開(kāi)發(fā)出高質(zhì)量軟件,并指導(dǎo)與開(kāi)發(fā)有關(guān)的一切過(guò)程。

從上面可以看出,OO并不是孤立的概念或技術(shù),而是一系列要素的復(fù)合體,并貫穿于整個(gè)軟件開(kāi)發(fā)周期。所以,僅僅從某個(gè)時(shí)間或控件切面切入而應(yīng)用OO,這樣的OO是不完整的,也不可能發(fā)揮出其應(yīng)有的作用。打個(gè)比方:如果使用OO的方法和工具進(jìn)行分析、設(shè)計(jì),但是編碼過(guò)程不能做到OO,就好比制造了一輛豪華的轎車(chē)卻找頭驢拉著走,是不能提高你出行效率的。反過(guò)來(lái),如果你是一個(gè)C#或Java高手,但分析設(shè)計(jì)過(guò)程不遵循OO,直到編碼時(shí)才用C#或Java試圖OO,這無(wú)異于你聽(tīng)說(shuō)開(kāi)車(chē)能提高出行速度,于是你苦學(xué)駕駛技術(shù),并掌握了高超的駕駛本領(lǐng),但最終卻坐在一頭驢子上,于是你開(kāi)始大喊:駕駛技術(shù)是騙人的!根本沒(méi)法用!是啊,驢子上連方向盤(pán)、離合器都沒(méi)有,空有一身駕駛本領(lǐng)又如何發(fā)揮出來(lái)呢。

這個(gè)系列的文章概要和內(nèi)容組織

這系列文章的大體寫(xiě)作方式,是通過(guò)一個(gè)實(shí)際案例《XX食品公司連鎖店在線定料系統(tǒng)》的調(diào)研、分析、設(shè)計(jì)、開(kāi)發(fā)等一系列過(guò)程,幫助大家更好的認(rèn)清OO如何實(shí)踐,同時(shí)澄清一些誤會(huì)。這個(gè)系統(tǒng)是我曾經(jīng)參與過(guò)的實(shí)際案例,為了文章需要,將進(jìn)行一定程度的修改,但一些很關(guān)鍵的東西都會(huì)原汁原味保留下來(lái)。在整個(gè)過(guò)程中,請(qǐng)各位不拘泥于具體技術(shù)相關(guān)問(wèn)題,而要一直保持一個(gè)較高的視端,一睹OO的全貌。

文章的大概組織方式:

第一部分:需求分析之前的故事

很多人認(rèn)為就軟件開(kāi)發(fā)來(lái)說(shuō),第一步是需求分析,其實(shí)非也。如果想更好實(shí)踐OO,需求分析之前還有很多工作,如特性調(diào)研、降低風(fēng)險(xiǎn)等環(huán)節(jié),這一部分我們講講需求分析之前的故事。

第二部分:分析步步高

這一部分開(kāi)始對(duì)系統(tǒng)進(jìn)行真正的分析,讓我們來(lái)看看OO是如何引導(dǎo)和指導(dǎo)我們分析的。

第三部分:設(shè)計(jì)的方方面面

設(shè)計(jì)是一個(gè)繁雜的過(guò)程,諸多OO原則與模式都會(huì)應(yīng)用于其中,這一部分不會(huì)細(xì)講各種原則及模式,而是看看正確應(yīng)用原則與模式的方式是怎么樣的。

第四部分:讓所有努力開(kāi)花結(jié)果

這一部分,我們將前面的成果付諸實(shí)踐。通過(guò)這一部分,可以清楚的看到前面做的一切工作都不是飄在云里的空中樓閣,而是開(kāi)發(fā)高質(zhì)量軟件不可缺少的部分。

以上是目前的規(guī)劃,當(dāng)然,在整個(gè)過(guò)程中可能會(huì)出現(xiàn)變化,但是大體條理不會(huì)打亂。希望本系列文章能給您帶來(lái)幫助。

二、第一項(xiàng)任務(wù):特性列表

第一份說(shuō)明

當(dāng)這個(gè)項(xiàng)目開(kāi)始時(shí),我們得到的關(guān)于我們要做的系統(tǒng)的唯一說(shuō)明是一頁(yè)Word文檔,這是一份簡(jiǎn)單的不能再簡(jiǎn)單的說(shuō)明。文檔里只有一行字:我們需要一個(gè)系統(tǒng),使得全國(guó)各地的代理加盟商和連鎖店能夠通過(guò)網(wǎng)絡(luò)訂購(gòu)原料。另外,我們還知道這是一個(gè)食品公司,主營(yíng)面包、麻花、肉夾饃等食品,在全國(guó)各地有多家連鎖機(jī)構(gòu)。除此之外,我們一無(wú)所知。

永遠(yuǎn)不要和客戶(hù)談需求

軟件開(kāi)發(fā)的第一步是什么?很多人覺(jué)得是需求分析。顯然這短短的一句說(shuō)明無(wú)法滿足我們的要求,于是很自然的,你希望找客戶(hù)談話,詳細(xì)了解情況,然后做出詳細(xì)的需求分析。于是,你心里有了這么一個(gè)算盤(pán):

和客戶(hù)談話 -> 問(wèn)清所有需求 -> 進(jìn)行需求分析 -> 生成需求文檔

乍看之下,這是很合理的步驟,但是實(shí)際上這是不可行的。原因有如下幾點(diǎn)。

1.客戶(hù)不關(guān)心系統(tǒng)的所有方面

每個(gè)開(kāi)發(fā)人員都希望,客戶(hù)可以清楚的把自己需要的東西的方方面面清楚無(wú)誤告訴你,然而,這只是一廂情愿罷了。因?yàn)椋魏我粋€(gè)客戶(hù)在需要什么東西的時(shí)候,只會(huì)大致想想要個(gè)什么東西,并不會(huì)將所有地方都仔細(xì)想清楚。

2.有時(shí)客戶(hù)并不清楚自己到底要什么東西

有時(shí)候,客戶(hù)并不是很清楚自己想要什么。這不是天方夜譚。很多時(shí)候,客戶(hù)僅僅有一個(gè)“想要實(shí)現(xiàn)某個(gè)目的的動(dòng)機(jī)”,而沒(méi)有“我需要一個(gè)什么系統(tǒng)”這么明確的概念。例如,從上文那個(gè)“一句話說(shuō)明”中,可以看出,我們的客戶(hù)僅僅是有一個(gè)動(dòng)機(jī):希望有一個(gè)系統(tǒng),能使得他們公司的代理商和加盟店在線定料,至于這是一個(gè)什么樣的系統(tǒng),他們并沒(méi)有明確的概念,更不用說(shuō)這個(gè)系統(tǒng)有什么樣具體的需求了。

基于以上兩點(diǎn),你是不可能從客戶(hù)那里問(wèn)清所有需求的。實(shí)際上,就不該和客戶(hù)談需求,因?yàn)樾枨髲膩?lái)就不是“客戶(hù)面”的東西,而是“開(kāi)發(fā)人員面”的東西。需求需要包含方方面面系統(tǒng)需要實(shí)現(xiàn)的功能,而客戶(hù)往往并沒(méi)有如此精細(xì)想過(guò),甚至客戶(hù)自己對(duì)自己想要的東西什么樣子都不清晰。面對(duì)這種客戶(hù),你一本正經(jīng)往他面前一坐,開(kāi)發(fā)筆記本說(shuō):“我們談?wù)勑枨蟀伞保蛘f(shuō)“我們進(jìn)行需求分析吧”,我想客戶(hù)會(huì)立馬崩潰,而你也不可能得到你想要的所有東西。

作為開(kāi)發(fā)人員,不應(yīng)該一開(kāi)始就和客戶(hù)談需求,而要先談特性。很多需求并不需要客戶(hù)告訴你,開(kāi)發(fā)人員應(yīng)該能通過(guò)常識(shí)識(shí)別出來(lái),就如沒(méi)有哪一個(gè)買(mǎi)汽車(chē)的客戶(hù)會(huì)說(shuō):我需要一個(gè)輛汽車(chē),要有方向盤(pán),還要有四個(gè)輪子。他們通常會(huì)說(shuō):“我要一輛家用車(chē)、要省油、舒適,要至少能坐3個(gè)人。”這“家用車(chē)”、“至少能坐三個(gè)人”就是特性。

特性是一些描述,一條特性簡(jiǎn)要描述了系統(tǒng)的一個(gè)客戶(hù)最關(guān)心的核心功能。

最為開(kāi)發(fā)人員,首要任務(wù)不是做需求分析,而是幫助用戶(hù)整理出一份特性列表。這里之所以說(shuō)“幫助”,是因?yàn)楹芏鄷r(shí)候,客戶(hù)由于自身太關(guān)注于某個(gè)方面,而漏掉了十分重要的特性,這是你要幫客戶(hù)想想,并將想到的特性詢(xún)問(wèn)客戶(hù)是否是需要的。如果客戶(hù)很高興的說(shuō)“對(duì)!對(duì)!”,那么這就是大功一件。所以,在初期階段,開(kāi)發(fā)人員一定要想客戶(hù)之所想,急客戶(hù)之所急,盡快幫客戶(hù)理清系統(tǒng)有什么特性。

所以,正確的過(guò)程應(yīng)該是:

詢(xún)問(wèn)客戶(hù)系統(tǒng)都有什么功能 -> 寫(xiě)出初期特性列表 -> 想想什么遺漏特性,并詢(xún)問(wèn)客戶(hù) -> 查漏補(bǔ)缺

生成特性列表

下面回到案例。

雖然客戶(hù)的說(shuō)明只有一句話,我們還是整理出一份初期的特性列表,并將其作為我們向客戶(hù)展示的第一份工作成果。這份特性列表內(nèi)容如下:

1.可以將各種原料信息發(fā)布到系統(tǒng)上

2.加盟商和連鎖店可以通過(guò)系統(tǒng)在線定料

沒(méi)錯(cuò),我們的初期文檔只有兩項(xiàng)特性。我們把這個(gè)給客戶(hù)看,客戶(hù)說(shuō):“嗯……大約是這個(gè)東西吧。”很顯然,我們的客戶(hù)是比較懶的那種,這時(shí),我們有義務(wù)引導(dǎo)客戶(hù)想起更多需要的特性。下面是當(dāng)時(shí)大約對(duì)話:       開(kāi)發(fā)人員(簡(jiǎn)稱(chēng)D),客戶(hù)(簡(jiǎn)稱(chēng)C)       D:你這個(gè)加盟商和連鎖店是要如何區(qū)分呢?       C:我們公司有一個(gè)加盟商和連鎖店的記錄。       D:那么你們是準(zhǔn)備將各個(gè)加盟商的信息全部錄入系統(tǒng)嗎?       C:不是,我希望他們能自己注冊(cè),就和論壇那種。       D:那么你要如何確認(rèn)他們的身份,總不能任何人都可以在這個(gè)系統(tǒng)注冊(cè)吧。       C:嗯,我們公司有各個(gè)加盟商的詳細(xì)信息,我們希望他們注冊(cè)時(shí)提供足夠的信息,我們進(jìn)行核對(duì)。       (于是我們飛快寫(xiě)下一個(gè)特性:加盟商和連鎖店通過(guò)網(wǎng)絡(luò)進(jìn)行注冊(cè),總店負(fù)責(zé)人審核后才可以正式使用系統(tǒng)。)D:你們得在后臺(tái)能發(fā)布各種原料的信息吧。       C:嗯,使得。       D:這里有沒(méi)有什么特別的要求。       C:沒(méi)有吧……       D:好的,那么你們準(zhǔn)備設(shè)立幾個(gè)人負(fù)責(zé)管理這個(gè)系統(tǒng)。       C:就一個(gè)人吧,就信息部那個(gè)。我們就這一個(gè)比較懂計(jì)算機(jī)的。       D:也就是說(shuō)不需要有多個(gè)人分別管理這個(gè)系統(tǒng)?       C:不需要。       (寫(xiě)下一個(gè)特性:系統(tǒng)需要一個(gè)管理員,可以對(duì)系統(tǒng)進(jìn)行管理) D:在你們的加盟商進(jìn)行定料時(shí),你希望他們?cè)趺床僮靼 ?      C:這個(gè),我沒(méi)仔細(xì)想過(guò)……       (看客戶(hù)對(duì)這個(gè)地方比較不清晰,我們打開(kāi)了一個(gè)網(wǎng)上書(shū)店的網(wǎng)站,給他演示了一下購(gòu)物車(chē)購(gòu)物的過(guò)程) D:你看,你的這個(gè)定料過(guò)程是不是和這個(gè)購(gòu)物過(guò)程很相似,加盟商定料是不是就相當(dāng)于從總公司購(gòu)買(mǎi)原料啊。       C:對(duì)對(duì)!就要這種效果的!       (這里要記住,在特性不能直接說(shuō)清楚時(shí),找相似事物是一個(gè)不錯(cuò)的選擇。也就是說(shuō),說(shuō)明這個(gè)特性像什么,不像什么)       (我們又加一條特性:使用購(gòu)物車(chē)功能進(jìn)行網(wǎng)上定料) D:付錢(qián)這一塊怎么弄,需要網(wǎng)上支付嗎?       C:不了,我們一般又財(cái)務(wù)專(zhuān)門(mén)做錢(qián)這一塊工作。       D:那買(mǎi)完原料后要不要什么憑證呢?       C:買(mǎi)完后生成一份定料單吧,打印出來(lái),交給財(cái)務(wù),財(cái)務(wù)清算款項(xiàng),款到賬后通知原料那邊發(fā)貨。       (又一條特性:定料完成后生成定料單,并可以打印) D:那么關(guān)于這些交易,你一定希望能查詢(xún)吧,你希望怎么查詢(xún)。       C:哦,這些我們財(cái)務(wù)那邊有專(zhuān)門(mén)的財(cái)務(wù)軟件。你這個(gè)系統(tǒng)只要能讓加盟商定料就行了。

到這里談話基本結(jié)束,我們得到如下一張補(bǔ)充過(guò)的特性列表:       1.可以將各種原料信息發(fā)布到系統(tǒng)上       2.加盟商和連鎖店可以通過(guò)系統(tǒng)在線定料       3.加盟商和連鎖店通過(guò)網(wǎng)絡(luò)進(jìn)行注冊(cè),總店負(fù)責(zé)人審核后才可以正式使用系統(tǒng)       4.系統(tǒng)需要一個(gè)管理員,可以對(duì)系統(tǒng)進(jìn)行管理       5.使用購(gòu)物車(chē)功能進(jìn)行網(wǎng)上定料       6.定料完成后生成定料單,并可以打印

我們將補(bǔ)充后的特性列表給客戶(hù)看了看,基本得到了認(rèn)可。

到了這里,我們第一步就差不多做完了。但是,我們還是不能馬上進(jìn)入需求分析,因?yàn)檫@之前還有很多事情要做。例如,特性整理,風(fēng)險(xiǎn)規(guī)避,這都是后面要討論的話題。

重點(diǎn)總結(jié) 1.客戶(hù)不會(huì)想到方方面面。       2.有時(shí)客戶(hù)并不明確自己想要什么東西,而僅僅是有個(gè)動(dòng)機(jī)。       3.不要和客戶(hù)談需求,要談特性。       4.開(kāi)發(fā)人員有義務(wù)引導(dǎo)和幫助客戶(hù)挖掘系統(tǒng)的特性。       5.當(dāng)客戶(hù)描述不清某個(gè)特性時(shí),可以采用找類(lèi)似事物的方法,說(shuō)說(shuō)這個(gè)特性像什么,不像什么。       6.在軟件開(kāi)發(fā)初期,我們需要首先整理出一張?zhí)匦粤斜恚皇亲鲂枨蠓治觥?/p>

三、降低風(fēng)險(xiǎn)

風(fēng)險(xiǎn)無(wú)處不在

在上一篇文章中,我們寫(xiě)出了一張?zhí)匦粤斜怼H缓笫遣皇蔷涂梢宰鲂枨蠓治隽耍亢苓z憾,還不可以,我們?nèi)杂性S多工作要做。拿到特性列表后第一件事,就是要盡量降低風(fēng)險(xiǎn)。這里先不長(zhǎng)篇大論風(fēng)險(xiǎn)如何如何,我們先做,從做的過(guò)程中體會(huì)降低風(fēng)險(xiǎn)的涵義。

DRY

這里,首先要引入一個(gè)OO原則——DRY。

DRY原則,全稱(chēng)Don"t Repeat Yourself,指:在系統(tǒng)中,每一個(gè)信息或行為片段應(yīng)該僅僅存在一份,且存在于合適的地方。

對(duì)于這個(gè)原則,很多朋友將其理解為“不要出現(xiàn)重復(fù)的代碼”,這是很片面的理解。其實(shí),OO本身并不是僅僅關(guān)于如何寫(xiě)出優(yōu)秀的代碼,而是關(guān)于如何開(kāi)發(fā)出優(yōu)秀的軟件。所以,很多OO原則并不是僅僅代碼層面的原則,而是可以應(yīng)用于整個(gè)開(kāi)發(fā)過(guò)程的。下面來(lái)著重看看這個(gè)原則的深層意義,以及討論其在降低風(fēng)險(xiǎn)中的應(yīng)用。

如何利用DRY降低風(fēng)險(xiǎn)

在所有的開(kāi)發(fā)風(fēng)險(xiǎn)中,有一種風(fēng)險(xiǎn),是由于同一個(gè)信息或行為片段分散于系統(tǒng)的不同地方,從而導(dǎo)致重復(fù)勞動(dòng),并且給修改和維護(hù)造成隱患。

下面,分別通過(guò)例子來(lái)描述兩種不良后果。

1.重復(fù)勞動(dòng)

例如,在特性列表中,如果兩個(gè)特性本身應(yīng)該是一個(gè)特性,但被誤認(rèn)為是兩個(gè)不同特性。那么所有基于特性的分析和設(shè)計(jì)都存在重復(fù)勞動(dòng),即對(duì)同一個(gè)特性,做了兩遍分析和設(shè)計(jì),直到發(fā)現(xiàn)重復(fù)為止。這個(gè)代價(jià)是巨大的。

2.修改和維護(hù)隱患

例如某一代碼段完全相似,但是出現(xiàn)在程序的諸多地方。這些相似的代碼段一定是完成完全相同的功能,于是有著“同生同滅”的特點(diǎn),即如果某段代碼要修改,一般來(lái)說(shuō)所有這段代碼的重復(fù)代碼都要修改。這就給維護(hù)帶來(lái)很大隱患。

DRY原則正是針對(duì)這種風(fēng)險(xiǎn)的一個(gè)解決方案。關(guān)于DRY在代碼中的應(yīng)用,暫且放下,這里只看它在特性列表整理中的應(yīng)用。顯然,根據(jù)DRY原則,要求特性列表中的特性不能具有重復(fù),那么我們?cè)僮屑?xì)看看我們的特性列表:       1.可以將各種原料信息發(fā)布到系統(tǒng)上       2.加盟商和連鎖店可以通過(guò)系統(tǒng)在線定料       3.加盟商和連鎖店通過(guò)網(wǎng)絡(luò)進(jìn)行注冊(cè),總店負(fù)責(zé)人審核后才可以正式使用系統(tǒng)       4.系統(tǒng)需要一個(gè)管理員,可以對(duì)系統(tǒng)進(jìn)行管理       5.使用購(gòu)物車(chē)功能進(jìn)行網(wǎng)上定料       6.定料完成后生成定料單,并可以打印

仔細(xì)檢查,不難發(fā)現(xiàn)2和5其實(shí)是在描述一個(gè)特性,于是我們將2和5合并成一個(gè)新的特性:加盟商和連鎖店可以使用購(gòu)物車(chē)功能在線定料。另外,可以看出,“總店負(fù)責(zé)人”和“管理員”其實(shí)是一個(gè)概念。整理完后,得到如下新特性列表:       1.可以將各種原料信息發(fā)布到系統(tǒng)上       2.加盟商和連鎖店可以使用購(gòu)物車(chē)功能在線定料       3.加盟商和連鎖店通過(guò)網(wǎng)絡(luò)進(jìn)行注冊(cè),管理員審核后才可以正式使用系統(tǒng)       4.系統(tǒng)需要一個(gè)管理員,可以對(duì)系統(tǒng)進(jìn)行管理       5.定料完成后生成定料單,并可以打印

再仔細(xì)檢查,已經(jīng)沒(méi)有重復(fù)特性。這樣,我們就應(yīng)用DRY原則規(guī)避了第一種風(fēng)險(xiǎn):重復(fù)勞動(dòng)的風(fēng)險(xiǎn)。下面給這種風(fēng)險(xiǎn)下一個(gè)定義:

重復(fù)勞動(dòng)風(fēng)險(xiǎn)——指由于重復(fù)特性的存在,導(dǎo)致對(duì)同一特性進(jìn)行了一遍以上的分析設(shè)計(jì)過(guò)程。最終導(dǎo)致資源浪費(fèi),開(kāi)發(fā)效率降低,可能導(dǎo)致無(wú)法按時(shí)交付。

知之為知之 不知為不知

在使用DRY整理完特性列表后,下一步就是要規(guī)避第二種風(fēng)險(xiǎn):概念模糊。

概念模糊風(fēng)險(xiǎn)——指由于開(kāi)發(fā)人員對(duì)于某一領(lǐng)域知識(shí)不熟悉,而將某一個(gè)概念想當(dāng)然,繼而根據(jù)這個(gè)想當(dāng)然的結(jié)果進(jìn)行分析設(shè)計(jì)。如果其想法錯(cuò)誤,則會(huì)導(dǎo)致系統(tǒng)無(wú)法正常使用或無(wú)法完成業(yè)務(wù)既定目的,從而導(dǎo)致返工或項(xiàng)目失敗。

很明顯,一般來(lái)說(shuō)開(kāi)發(fā)人員并不是業(yè)務(wù)專(zhuān)家。所以對(duì)于領(lǐng)域業(yè)務(wù)不熟悉是很正常的,作為一個(gè)合格開(kāi)發(fā)人員,應(yīng)該謹(jǐn)遵孔老夫子“知之為知之,不知為不知”這一教誨,謹(jǐn)慎負(fù)責(zé)對(duì)待不熟悉的概念,而不能從字面臆想。正確的做法是,首先審視特性列表,對(duì)于不熟悉或拿不準(zhǔn)的概念,去請(qǐng)教領(lǐng)域?qū)<一蚩蛻?hù)。下面繼續(xù)以我們的項(xiàng)目為例。

經(jīng)過(guò)對(duì)特性列表的分析,我們找出以下疑問(wèn)或模糊概念:

1.原料(都是什么原料,需要分類(lèi)么?)

2.加盟商和連鎖店(兩者有什么區(qū)別?定料業(yè)務(wù)流程一樣么?)

帶著著兩個(gè)疑問(wèn),我們?cè)俅伟菰L了客戶(hù)。具體交談就不說(shuō)了,最后我們得到了如下結(jié)果。

1.原料主要就是些炸粉、調(diào)料之類(lèi)的配方需要保密的烹飪?cè)希瑳](méi)有太特別的,不需分類(lèi)。

2.加盟商和連鎖店不是一個(gè)概念,加盟商直屬總公司,連鎖店可能直屬總公司也可能直屬某加盟商。加盟商和直屬總公司的連鎖店直接向總公司定料,不直屬的的連鎖店向相應(yīng)加盟商領(lǐng)取原料。連鎖店按原價(jià)定料,加盟商按照等級(jí)分為5級(jí),每級(jí)折扣不同。

經(jīng)過(guò)以上一番了解,我們基本把模糊概念搞清楚了,并且經(jīng)過(guò)這么一了解,我們的特性列表隨之改變:       1.可以將各種原料信息發(fā)布到系統(tǒng)上       2.加盟商和連鎖店可以使用購(gòu)物車(chē)功能在線定料       3.加盟商和連鎖店通過(guò)網(wǎng)絡(luò)進(jìn)行注冊(cè),管理員審核后才可以正式使用系統(tǒng)       4.系統(tǒng)需要一個(gè)管理員,可以對(duì)系統(tǒng)進(jìn)行管理       5.定料完成后生成定料單,并可以打印       6.直屬連鎖店按原價(jià)定料,加盟商按照等級(jí)分為5級(jí),每級(jí)折扣不同

我們認(rèn)為加盟商級(jí)別和折扣是很重要的特性,于是把它加到了特性列表里。

保證我們能夠?qū)崿F(xiàn)

上面我們已經(jīng)避免了兩種風(fēng)險(xiǎn)。現(xiàn)在再來(lái)看一種風(fēng)險(xiǎn)。舉個(gè)例子,如果一個(gè)建筑設(shè)計(jì)師,設(shè)計(jì)了一座新型別墅,其中有一條特性是:院子里有一個(gè)季節(jié)調(diào)節(jié)裝置,可以隨意將院子里的季節(jié)調(diào)節(jié)為春夏秋冬中任意一個(gè)季節(jié)。你們認(rèn)為這個(gè)特性怎么樣?很酷的創(chuàng)意對(duì)不對(duì)?但是如果你是別墅的客戶(hù),你會(huì)這么想?我想你不會(huì)和設(shè)計(jì)師一起為這個(gè)非常酷的特性而激動(dòng),你會(huì)首先問(wèn)設(shè)計(jì)師要怎么實(shí)現(xiàn)這個(gè)功能。沒(méi)錯(cuò),可以調(diào)節(jié)季節(jié)的院子是很棒,可以不要忘了,最終我們的別墅是要建筑在實(shí)際中的,而實(shí)際總會(huì)有諸多約束不能讓每一個(gè)想法變成現(xiàn)實(shí)。

同上。無(wú)論我們?cè)O(shè)計(jì)的東西多么天花亂墜,最終都是要編碼實(shí)現(xiàn)的。所以,我們要保證所有的特性可以在編碼層級(jí)上有解決方案。即使我們不能馬上知道精確的解決方案,但也要大體知道怎么實(shí)現(xiàn)。由此引出了第三種風(fēng)險(xiǎn):

實(shí)現(xiàn)能力風(fēng)險(xiǎn)——指由于某項(xiàng)特性不能由具體技術(shù)解決帶來(lái)的風(fēng)險(xiǎn)。這種風(fēng)險(xiǎn)包括兩個(gè)層面,第一是現(xiàn)有技術(shù)完全解決不了。第二是由于開(kāi)發(fā)團(tuán)隊(duì)沒(méi)有解決方案。這種風(fēng)險(xiǎn)可能導(dǎo)致項(xiàng)目延期甚至失敗。

要規(guī)避這種風(fēng)險(xiǎn),就要逐一審查我們的特性是否可以在現(xiàn)有技術(shù)范圍內(nèi)解決。仔細(xì)審查后,第一個(gè)層面應(yīng)該是沒(méi)有問(wèn)題,所有這6種特性都可以在現(xiàn)有技術(shù)內(nèi)解決。但是對(duì)于特性2,我們存在一定問(wèn)題。因?yàn)楫?dāng)時(shí)我們都沒(méi)有設(shè)計(jì)購(gòu)物車(chē)的經(jīng)驗(yàn),一下子不知購(gòu)物車(chē)是如何實(shí)現(xiàn)的。

為了解決這個(gè)問(wèn)題,要做如下工作。這里要注意,我們?cè)谶@里可能討論了很多細(xì)節(jié),但是我們要避免提前進(jìn)入細(xì)節(jié)。所以,這里討論的所有細(xì)節(jié)并不是要進(jìn)行分析或設(shè)計(jì),而僅僅是通過(guò)頭腦風(fēng)暴的方式大約有個(gè)譜。這個(gè)“譜”往往和最終的實(shí)現(xiàn)有很大不同,但是至少我們知道這個(gè)特性通過(guò)某種方式可以實(shí)現(xiàn)。

在遇到這種風(fēng)險(xiǎn)時(shí),首先要做的是查找相關(guān)資料。在查找了一些資料后,我們了解到購(gòu)物車(chē)一般分為Session實(shí)現(xiàn)方式和數(shù)據(jù)庫(kù)實(shí)現(xiàn)方式。這兩種方式特點(diǎn)不同,前者支持未登錄購(gòu)物,確不能保存客戶(hù)購(gòu)物信息。而后一種又必須登錄后才能購(gòu)物。這里涉及到客戶(hù)的利益,所以要由客戶(hù)決定。

于是,我們?cè)儐?wèn)了客戶(hù),得到的答復(fù)是“未登錄時(shí)要可以定料,而且也要保持定料信息。”這句話有點(diǎn)模糊,但大體可以知道客戶(hù)的意思,于是我們改寫(xiě)成如下一段話“未登錄的用戶(hù)可以使用購(gòu)物車(chē),但不能下定料單,登錄后才可下單。登錄用戶(hù)可以保持購(gòu)物車(chē)中信息。”我們拿給客戶(hù)看,并進(jìn)行了一定描述,客戶(hù)認(rèn)同了這個(gè)決策。

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

在經(jīng)過(guò)一番討論后,我們都同意的解決方案是“未登錄的用戶(hù)使用Session處理購(gòu)物車(chē),登錄的使用數(shù)據(jù)庫(kù)存儲(chǔ)購(gòu)物信息。當(dāng)用戶(hù)登錄時(shí),如果Session中有將購(gòu)物信息,將Session中的信息轉(zhuǎn)入數(shù)據(jù)庫(kù)。”

這個(gè)討論可以到此為止了。因?yàn)槲覀儾恍枰_,我們只要大致心里有個(gè)譜就行了。

重點(diǎn)總結(jié)1.特性列表完成后,我們首先應(yīng)該降低風(fēng)險(xiǎn),而不是做分析或設(shè)計(jì)。       2.重復(fù)特性存在風(fēng)險(xiǎn)。可以用DRY原則處理。       3.存在模糊不清概念的特性存在風(fēng)險(xiǎn)。請(qǐng)仔細(xì)詢(xún)問(wèn)客戶(hù),不要想當(dāng)然。       4.不知如何實(shí)現(xiàn)的特性存在風(fēng)險(xiǎn)。一定要保證對(duì)每條特性的實(shí)現(xiàn)方式心里大致有個(gè)譜,但不需很精確。

四、通覽全局:避免過(guò)早陷入細(xì)節(jié)的泥沼

細(xì)節(jié)的泥沼

現(xiàn)在我們?cè)俅螌⑻匦粤斜碣N過(guò)來(lái):       1.可以將各種原料信息發(fā)布到系統(tǒng)上       2.加盟商和連鎖店可以使用購(gòu)物車(chē)功能在線定料       3.加盟商和連鎖店通過(guò)網(wǎng)絡(luò)進(jìn)行注冊(cè),管理員審核后才可以正式使用系統(tǒng)       4.系統(tǒng)需要一個(gè)管理員,可以對(duì)系統(tǒng)進(jìn)行管理       5.定料完成后生成定料單,并可以打印       6.直屬連鎖店按原價(jià)定料,加盟商按照等級(jí)分為5級(jí),每級(jí)折扣不同

我們已經(jīng)和這則列表折騰很久了,相信很多朋友已經(jīng)厭倦了,肯定在想:不要在折騰這該死的特性列表了,趕快開(kāi)始吧。這點(diǎn)我同意。但是要開(kāi)始做什么?很多朋友可能會(huì)說(shuō):開(kāi)始用例分析吧。說(shuō)實(shí)話,用例是好東西,它讓我們清晰認(rèn)識(shí)到系統(tǒng)的工作流程,正式因?yàn)檫^(guò)于清晰,所以很容易讓我們陷入一個(gè)細(xì)節(jié)的泥沼。

應(yīng)該說(shuō),從“特性列表”直接到“用例分析”不是一個(gè)好注意,因?yàn)樘匦粤斜黻P(guān)注于功能(Function),而用例關(guān)注于系統(tǒng)的業(yè)務(wù)流(Business Flow),我們從功能直接開(kāi)始分析系統(tǒng)的細(xì)節(jié)業(yè)務(wù)流,這個(gè)跨越太大,不利于軟件質(zhì)量的保證。特性是相對(duì)分散獨(dú)立的功能描述,而用例是系統(tǒng)細(xì)節(jié),很明顯,在這之間應(yīng)該有一個(gè)過(guò)渡,而這個(gè)過(guò)渡,就是一個(gè)高層次的,從全局角度對(duì)系統(tǒng)的一個(gè)概觀認(rèn)識(shí)。這個(gè)概觀認(rèn)識(shí)起到承上啟下的作用,既將特性列表映射為一個(gè)系統(tǒng)的大概模型,又給系統(tǒng)細(xì)節(jié)的分析奠定了基礎(chǔ)。所以,在系統(tǒng)特性基本確定后,我們首先要從全局給出一個(gè)系統(tǒng)的概覽,避免落入用例分析這樣細(xì)節(jié)的泥沼。

概覽系統(tǒng)的有力工具——用例圖

既然我們要給出一個(gè)全局的系統(tǒng)概覽,自然就需要有一種方式將其表達(dá)出來(lái)。顯然,僅僅通過(guò)說(shuō)是不理想的,我們需要一種能用于書(shū)面表達(dá)的工具,而這個(gè)工具,就是我們非常熟悉的UML圖之一的用例圖。

很多朋友可能有疑問(wèn),上面不是說(shuō)不進(jìn)行用例分析嗎?怎么這里又畫(huà)用例圖了?因?yàn)橛美陀美龍D表述的信息層面完全不同,用例更傾向于細(xì)節(jié)和業(yè)務(wù)流的描述,而用例圖傾向于整體的描述。下面給出兩種工具要表述的信息:

用例——表述某個(gè)交互操作的動(dòng)作執(zhí)行者、用例名稱(chēng)、具體流程過(guò)程、例外情況等。

用例圖——表述系統(tǒng)有哪些執(zhí)行者、有哪些用例以及執(zhí)行者于用例、用例于用例之間的關(guān)系。

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

下面,我們就使用用例圖,從高層次角度看看系統(tǒng)的樣子。在這里還要說(shuō)明的是,隨著UML和用例分析技術(shù)的發(fā)展,提出了業(yè)務(wù)用例和系統(tǒng)用例的區(qū)別,而且用例存在不同的粒度。在進(jìn)行高層次概覽的時(shí)候,我們是使用的是一種粒度比較粗的用例圖。也許在以后的需求分析中,我們還會(huì)使用粒度更細(xì)的用例圖。

通過(guò)簡(jiǎn)要對(duì)特性列表的分析,可以畫(huà)出一張如下的用例圖:

可以看到,這個(gè)用例圖并沒(méi)有太多細(xì)節(jié)的東西,而僅僅描述了三個(gè)信息:1.系統(tǒng)有哪些用戶(hù) 2.系統(tǒng)有哪些操作 3.系統(tǒng)和用戶(hù)有哪些交互。這些,就是我們要的一個(gè)系統(tǒng)概觀。

用例圖的驗(yàn)證

畫(huà)完用例圖,我們并不是就完事了。因?yàn)椋沟糜美龍D真的是全局概觀,就一定要保證一點(diǎn):圖中用例覆蓋了所有特性。如果不能覆蓋所有特性,說(shuō)明我們的用例圖中缺少用例甚至缺少動(dòng)作執(zhí)行者。現(xiàn)在我們來(lái)驗(yàn)證一下:       特性1覆蓋于“原料管理”。       特性2覆蓋于“在線定料”。       特性3覆蓋于“注冊(cè)”和“加盟商和連鎖店管理”。       特性4覆蓋于“原料管理”和“加盟商和連鎖店管理”。       特性5覆蓋于“打印定料單”。       特性6覆蓋于...???

我們忽然發(fā)現(xiàn)一點(diǎn),這里并沒(méi)有和折扣有關(guān)的東西,那么這個(gè)特性沒(méi)有被用例覆蓋。我們知道,如果要實(shí)現(xiàn)這個(gè)特性,系統(tǒng)中一定要有一定的折扣機(jī)制,而一定是有管理員設(shè)置的。于是我們?cè)黾右粋€(gè)“折扣管理”用例。注意,這里我們可以先不陷入細(xì)節(jié),僅僅知道系統(tǒng)有這么一個(gè)折扣機(jī)制,至于具體怎么實(shí)現(xiàn),到分析設(shè)計(jì)階段再討論。于是,修改后的用例圖如下:

現(xiàn)在我們可以說(shuō):特性6覆蓋于“折扣管理”和“在線定料”。

好了,這樣我們已經(jīng)確認(rèn),用例圖的用例覆蓋所有特性。

重點(diǎn)總結(jié) 1.不要過(guò)早陷入細(xì)節(jié)       2.在特性列表到用例分析之間,用該先有一個(gè)系統(tǒng)概覽,讓我們從高層次上審視系統(tǒng)全貌。       3.用例圖是實(shí)現(xiàn)這種概覽的有效方式。       4.用例不要粒度過(guò)細(xì),要能反應(yīng)系統(tǒng)粗粒度操作。       5.最后不要忘了檢查圖中用例是否覆蓋了所有特性。

五、需求分析之前的故事

高質(zhì)量軟件的第一要素

到目前為止,我們做了很多工作,但是我一直在強(qiáng)調(diào)這些都還不是需求分析。在很多人心目中,軟件開(kāi)發(fā)的第一件事就是先做需求分析。那么我們?yōu)槭裁床贿@樣做呢?這牽扯到一個(gè)關(guān)鍵的問(wèn)題:我們都希望開(kāi)發(fā)高質(zhì)量的軟件,而本系列文章的重點(diǎn)也是如何通過(guò)OO實(shí)踐開(kāi)發(fā)高質(zhì)量軟件,那么什么是高質(zhì)量軟件?

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

知道了這點(diǎn),就知道為什么第一步不是做需求分析了,因?yàn)樾枨蠓治龅闹攸c(diǎn)不是“讓軟件做客戶(hù)希望它做的事”,而是“將需求分解歸納成開(kāi)發(fā)人員容易進(jìn)行領(lǐng)域分析和設(shè)計(jì)的信息片段”。所以,需求分析是開(kāi)發(fā)人員面的東西,而不是客戶(hù)面的東西。作為開(kāi)發(fā)人員,我們要首先站在客戶(hù)的角度看問(wèn)題,而不能總是站在開(kāi)發(fā)人員角度,和客戶(hù)隔著一條河對(duì)話。我們要走過(guò)去,去河的另一岸。

回顧我們的工作

現(xiàn)在來(lái)總結(jié)一下我們目前所做的工作,你會(huì)發(fā)現(xiàn),我們所做的全部工作,其目的就是讓軟件做客戶(hù)希望它做的事。

我們首先總結(jié)出特性列表,然后通過(guò)分析和詢(xún)問(wèn)降低了風(fēng)險(xiǎn),同時(shí)修改了特性列表,最后從做出一張用例圖,使得從全局角度對(duì)系統(tǒng)進(jìn)行一個(gè)概覽。所有這一切,其實(shí)都是開(kāi)發(fā)人員在“努力變成客戶(hù)”,或說(shuō)努力讓自己站在客戶(hù)的角度看系統(tǒng),真正了解客戶(hù)想讓希望做什么。因?yàn)椋詈玫睦斫庑枨蟮姆绞骄褪抢斫饪蛻?hù)想讓系統(tǒng)做什么。

我們?cè)谀睦铮靠纯吹貓D吧

做了這么多工作,是不是有點(diǎn)迷失方向的感覺(jué)?似乎我們已經(jīng)迷失在OO從林中,不知現(xiàn)在身在何處。好的,那我們看看“OO地圖”吧,一方面搞清楚我們?cè)谑裁吹胤剑硪环矫婵纯次覀兒罄m(xù)有哪些路要走。

以上就是實(shí)踐中的大致開(kāi)發(fā)流程。一般來(lái)說(shuō),開(kāi)發(fā)大致分為兩個(gè)階段:前一階段我們要站在用戶(hù)角度,搞清用戶(hù)想要系統(tǒng)做什么;后一階段要回到開(kāi)發(fā)人員角度,進(jìn)行分析、設(shè)計(jì)、編碼、測(cè)試等一系列操作。而我們現(xiàn)在正處在兩個(gè)階段的交界處。

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

重點(diǎn)總結(jié)1.高質(zhì)量軟件的第一要素是:軟件做客戶(hù)希望它做的事。       2.在開(kāi)發(fā)初期,我們要盡量站在客戶(hù)角度。       3.理解需求的最好方法是明白客戶(hù)希望軟件做什么。       4.開(kāi)發(fā)流程大約分為兩個(gè)階段:搞清用戶(hù)想要系統(tǒng)做什么和迭代開(kāi)發(fā)。

六、迭代式開(kāi)發(fā)與用例驅(qū)動(dòng)

再次明晰開(kāi)發(fā)流程

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

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

在一般開(kāi)發(fā)流程中,直觀上可以分為兩個(gè)部分:業(yè)務(wù)階段和系統(tǒng)階段。明確這一點(diǎn)非常重要。其中業(yè)務(wù)階段主要進(jìn)行的工作是與計(jì)算機(jī)無(wú)關(guān)的,而系統(tǒng)階段才是和計(jì)算機(jī)相關(guān)的東西。上圖中“我們?cè)谶@里”那道豎線所指的地方,就是業(yè)務(wù)階段和系統(tǒng)階段的分界點(diǎn)。

而如果從建模角度分析,整個(gè)開(kāi)發(fā)流程分為四個(gè)子流程:       a)業(yè)務(wù)建模流程       b)系統(tǒng)建模流程       c)分析設(shè)計(jì)建模流程       d)部署實(shí)施建模流程       其中a)屬于業(yè)務(wù)階段,而b)c)d)均屬于系統(tǒng)階段。

業(yè)務(wù)建模流程的任務(wù)就是做業(yè)務(wù)分析、降低風(fēng)險(xiǎn)和給出系統(tǒng)總體概覽模型。系統(tǒng)建模主要就是需求工程。分析設(shè)計(jì)建模就是我們熟悉的概要設(shè)計(jì)和詳細(xì)設(shè)計(jì)。而部署實(shí)施建模是對(duì)系統(tǒng)的具體實(shí)施建立模型。

其中,我們一般所說(shuō)的“需求”,實(shí)際是指“系統(tǒng)需求”,是在b)階段進(jìn)行的,所以a)階段的一切工作,都不能算是需求分析。(當(dāng)然,如果加一個(gè)前綴,說(shuō)是“業(yè)務(wù)需求分析”,也是可以的,但是一般在軟件工程領(lǐng)域,說(shuō)“需求分析”是特指“系統(tǒng)需求分析”。)

而關(guān)于用例圖的疑惑,大家應(yīng)該知道,用例圖分為業(yè)務(wù)用例圖和系統(tǒng)用例圖,而業(yè)務(wù)用例圖產(chǎn)生于a)流程,這樣它們當(dāng)然會(huì)出現(xiàn)在b)流程,也就是需求分析之前。當(dāng)然,在b)流程中還會(huì)出現(xiàn)用例圖,這時(shí)就是系統(tǒng)用例圖了。

明白了以上開(kāi)發(fā)流程,我想很多疑惑就自然解開(kāi)了。所以,其實(shí)我們所謂的“需求分析之前的故事”,就是業(yè)務(wù)建模流程。

系統(tǒng)階段的法寶1:迭代與增量

在上文中,我們提到軟件過(guò)程大體分為業(yè)務(wù)階段是系統(tǒng)階段。在前面幾篇文章中,我們已經(jīng)基本完成業(yè)務(wù)階段,下面是進(jìn)入系統(tǒng)階段了。不過(guò)莫急,在正式進(jìn)入系統(tǒng)階段之前,我們有幾個(gè)重要的、關(guān)于系統(tǒng)階段的話題要聊一下。

如果你問(wèn)我,在系統(tǒng)階段最應(yīng)該被牢記的是什么,我會(huì)告訴你,是兩個(gè)詞:迭代&增量。

我們已經(jīng)知道,系統(tǒng)階段是在業(yè)務(wù)階段的基礎(chǔ)上,在計(jì)算機(jī)領(lǐng)域內(nèi)進(jìn)行需求分析、系統(tǒng)分析、概要設(shè)計(jì)、詳細(xì)設(shè)計(jì)、編碼、測(cè)試、部署實(shí)施等一系列環(huán)節(jié)。但是,如果你想僅施行一遍這個(gè)流程,而完成整個(gè)系統(tǒng)的話,不好意思,你大致會(huì)精神崩潰。

如果這個(gè)過(guò)程僅實(shí)施一遍,其實(shí)就成了瀑布模型。小系統(tǒng)也許可以,但是稍大點(diǎn)的系統(tǒng),將會(huì)帶來(lái)嚴(yán)重的后果。我們知道,“軟件開(kāi)發(fā)中永遠(yuǎn)不變的就是變化”,如果采用瀑布模型,反饋將會(huì)非常靠后,一直要到部署實(shí)施階段才能看到成果,如果客戶(hù)要求更改需求或認(rèn)為當(dāng)前系統(tǒng)不是他們想要的,那么修改過(guò)程會(huì)異常慘烈,代價(jià)也是巨大的。

那么,我們應(yīng)該如何實(shí)施系統(tǒng)階段開(kāi)發(fā)呢?法寶就是迭代和增量。具體做法是:

我們將整個(gè)系統(tǒng)分為許多相對(duì)獨(dú)立的“單元”,每次只對(duì)一個(gè)或少數(shù)幾個(gè)單元實(shí)施需求分析、系統(tǒng)分析、概要設(shè)計(jì)、詳細(xì)設(shè)計(jì)、編碼、測(cè)試、部署實(shí)施等一系列過(guò)程,一次這樣的過(guò)程叫做一次迭代,而將一次迭代的成果加入現(xiàn)有成果的過(guò)程就叫做增量。

這種開(kāi)發(fā)流程的優(yōu)勢(shì)是明顯的:我們總是能在相對(duì)較短的時(shí)間內(nèi),完成整個(gè)系統(tǒng)功能的一個(gè)“子集”,這個(gè)子集是可以運(yùn)行的,可以看到效果,所以如果用戶(hù)不滿意,反饋是及時(shí)的,修改代價(jià)也較小。通過(guò)合理的過(guò)程控制,變更代價(jià)總可以控制在一個(gè)可以接受的范圍內(nèi)。

在實(shí)施迭代&增量過(guò)程時(shí),要注意一下兩點(diǎn):

1)迭代單元不是環(huán)節(jié),而是系統(tǒng)功能的某個(gè)子集。如不能說(shuō)第一次迭代完成需求分析、第二次迭代完成設(shè)計(jì)……這不叫迭代式開(kāi)發(fā),這叫里程碑式開(kāi)發(fā),和迭代有本質(zhì)區(qū)別。

2)每次迭代一定要完整完成需求分析、系統(tǒng)分析、概要設(shè)計(jì)、詳細(xì)設(shè)計(jì)、編碼、測(cè)試、部署實(shí)施這一套環(huán)節(jié),產(chǎn)生的成果必須是成品,是可運(yùn)行、可交付的,是整個(gè)系統(tǒng)的一個(gè)子集,而不能是一個(gè)半成品。

系統(tǒng)階段的法寶2:用例驅(qū)動(dòng)

相信,大家或多或少聽(tīng)說(shuō)過(guò)“用例驅(qū)動(dòng)”。那么什么是用例驅(qū)動(dòng)呢?如果你理解了上文的迭代&增量過(guò)程,就很好理解用例驅(qū)動(dòng)了。上文不是說(shuō)過(guò),迭代時(shí)每次選取一個(gè)或少數(shù)幾個(gè)“單元”嗎?那么這個(gè)“單元”是什么?理論上,什么都可以,只要是對(duì)系統(tǒng)合理的劃分。但在實(shí)踐中,人們發(fā)現(xiàn),使用業(yè)務(wù)用例作為迭代單元是最合適的。為什么呢?       其一,業(yè)務(wù)用例大小適中,規(guī)模平均。       其二,業(yè)務(wù)用例大多相互獨(dú)立性好,適合進(jìn)行迭代。       其三,業(yè)務(wù)用例能很好反映系統(tǒng)的功能單元。

所以,所謂的用例驅(qū)動(dòng)就是以業(yè)務(wù)用例作為迭代單元進(jìn)行迭代開(kāi)發(fā)的流程。

你看,我們前面做了那么多業(yè)務(wù)分析,其中成果之一就是業(yè)務(wù)用例圖。而這里,業(yè)務(wù)用例成了我們進(jìn)行系統(tǒng)迭代開(kāi)發(fā)的單元和驅(qū)動(dòng)者,所以,軟件開(kāi)發(fā)過(guò)程不是割裂的,而是相互聯(lián)系的,不會(huì)說(shuō)上一個(gè)階段過(guò)去就過(guò)去了,和下一階段毫無(wú)聯(lián)系。一般,上一階段的產(chǎn)品總會(huì)成為下一階段的材料。

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

本文理論講得多了點(diǎn),有點(diǎn)枯燥,但是必須講,因?yàn)槊靼走@些是以后進(jìn)行系統(tǒng)階段的基礎(chǔ)。從下一篇開(kāi)始,我們回歸示例,進(jìn)入真正的系統(tǒng)階段了。下一篇,將開(kāi)始第一輪迭代的起始階段:需求分析。

重點(diǎn)總結(jié) 1.軟件過(guò)程大致可分為業(yè)務(wù)階段和系統(tǒng)階段。       2.業(yè)務(wù)階段進(jìn)行業(yè)務(wù)建模流程,與計(jì)算機(jī)領(lǐng)域無(wú)關(guān);系統(tǒng)階段進(jìn)行系統(tǒng)建模、分析設(shè)計(jì)建模和部署建模階段,與計(jì)算機(jī)相關(guān)。       3.系統(tǒng)階段的兩大法寶:迭代式開(kāi)發(fā)與用例驅(qū)動(dòng)。

七、【第一輪迭代】需求分析與領(lǐng)域分析

在前面,我們花了六篇文章的篇幅去討論需求分析之前發(fā)生的事情,這些內(nèi)容看起來(lái)枯燥或飄渺,但實(shí)際是為真正開(kāi)始系統(tǒng)的分析、設(shè)計(jì)和實(shí)現(xiàn)進(jìn)行的必要準(zhǔn)備。從這篇開(kāi)始,將正式進(jìn)入系統(tǒng)的開(kāi)發(fā)階段。這一篇文章,將討論第一輪迭代過(guò)程中的需求分析和領(lǐng)域分析環(huán)節(jié)。

選取第一輪迭代要實(shí)現(xiàn)的特性

回顧前面章節(jié),我們說(shuō)到,“迭代與增量”和“用例驅(qū)動(dòng)”是系統(tǒng)開(kāi)發(fā)的兩大法寶。另外,指出了如下幾個(gè)要點(diǎn):

1)迭代單元不是環(huán)節(jié),而是系統(tǒng)功能的某個(gè)子集。如不能說(shuō)第一次迭代完成需求分析、第二次迭代完成設(shè)計(jì)……這不叫迭代式開(kāi)發(fā),這叫里程碑式開(kāi)發(fā),和迭代有本質(zhì)區(qū)別。

2)每次迭代一定要完整完成需求分析、系統(tǒng)分析、概要設(shè)計(jì)、詳細(xì)設(shè)計(jì)、編碼、測(cè)試、部署實(shí)施這一套環(huán)節(jié),產(chǎn)生的成果必須是成品,是可運(yùn)行、可交付的,是整個(gè)系統(tǒng)的一個(gè)子集,而不能是一個(gè)半成品。

所以,說(shuō)白了,這第一步就是要從前面得到的特性列表或業(yè)務(wù)用例分析文檔中選取一個(gè)或幾個(gè)特性或業(yè)務(wù)用例進(jìn)行實(shí)現(xiàn)。(因?yàn)樘匦院蜆I(yè)務(wù)用例有對(duì)等映射關(guān)系,所以,從特性列表或業(yè)務(wù)用例分析文檔中選取迭代功能點(diǎn)在理論上是等價(jià)的。)這里,我們從特性列表選取特性。那么首先把我們前面完成的特性列表再搬出來(lái):

上圖就是我們前面得出的特性列表,總共有六個(gè)特性。理論上,第一輪選取哪些,總共選取幾個(gè),沒(méi)有明確的規(guī)定,但是,在選取特性方面,還是有一定經(jīng)驗(yàn)可以遵循的,大致有如下原則:

1)就選取個(gè)數(shù)來(lái)說(shuō),與迭代周期有關(guān)。一般的迭代開(kāi)發(fā)中,一個(gè)迭代周期大多選在一周到兩周之間,不宜多于兩周,所以,每個(gè)周期選擇的特性要估算能在這個(gè)周期內(nèi)完成。(順便說(shuō)一下,在每個(gè)周期內(nèi),如果發(fā)現(xiàn)時(shí)間不夠,做不完計(jì)劃,應(yīng)削減一些特性推入下個(gè)周期,切不可延長(zhǎng)周期。另外,切不可在周期開(kāi)始后添加任務(wù)。)

2)就選取的特性來(lái)說(shuō),最好是比較內(nèi)聚的幾個(gè)特性。也就是說(shuō),每個(gè)周期選取的特性,要盡量關(guān)聯(lián)緊密,而和其他周期的特性要盡量耦合度低。

3)就選取順序來(lái)說(shuō),因?yàn)橐竺恳粋€(gè)周期都要產(chǎn)生一個(gè)可運(yùn)行的子集系統(tǒng),所以,最好先選取平臺(tái)性、基礎(chǔ)性、對(duì)外依賴(lài)弱的特性,再選取功能性、對(duì)外依賴(lài)強(qiáng)的特性。例如,在這個(gè)例子中,如果第一輪迭代選擇特性2則不是一個(gè)好主意。因?yàn)橘?gòu)物車(chē)功能要依賴(lài)于管理員、加盟商、物料等諸多特性,在后者沒(méi)有實(shí)現(xiàn)之前,很難單獨(dú)做出一個(gè)可運(yùn)行的購(gòu)物車(chē)子集系統(tǒng)。

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

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

領(lǐng)域分析

在確定迭代特性后,下一步要進(jìn)行領(lǐng)域分析。領(lǐng)域分析就是針對(duì)特性涉及到的實(shí)體及實(shí)體間的關(guān)系進(jìn)行一個(gè)分析,構(gòu)造出靜態(tài)領(lǐng)域模型。這里要注意三點(diǎn):1、領(lǐng)域模型是靜態(tài)模型;2、領(lǐng)域模型要反映的是實(shí)體及實(shí)體見(jiàn)得靜態(tài)關(guān)系(例如包含等,而調(diào)用這類(lèi)動(dòng)態(tài)關(guān)系不該在這里出現(xiàn));3、領(lǐng)域模型是比較高視角的模型,其中的實(shí)體和最終程序中的實(shí)體類(lèi)未必對(duì)應(yīng)。

領(lǐng)域分析的方法有很多,下面我使用一種我總結(jié)的領(lǐng)域分析方法。流程如下:

step1、提取特性中的名詞

我們這個(gè)迭代周期內(nèi)涉及的特性是3、4和6,從中可提取出如下名詞:加盟商,連鎖店,網(wǎng)絡(luò),管理員,系統(tǒng),直屬連鎖店,原價(jià),等級(jí),折扣。注意,這些名詞就是領(lǐng)域?qū)嶓w的候選者。

step2、篩選名詞,確定實(shí)體

不是所有候選名詞都是領(lǐng)域中的實(shí)體,這一步要對(duì)候選者進(jìn)行篩選。這一步非常重要,也相對(duì)難度較高,需要結(jié)合經(jīng)驗(yàn)和前面的客戶(hù)談?wù)摬牧稀⑿枨笥涗浀龋匾獣r(shí),要咨詢(xún)客戶(hù)或業(yè)務(wù)專(zhuān)家。下面我們進(jìn)行篩選。

首先,“網(wǎng)絡(luò)”顯然不是領(lǐng)域內(nèi)的實(shí)體,排除。“系統(tǒng)”是對(duì)整個(gè)產(chǎn)品的總稱(chēng),也比較明顯不是領(lǐng)域?qū)嶓w,排除。排除了兩個(gè)明顯的“干擾項(xiàng)”,下面看幾個(gè)可疑的家伙,這里,我發(fā)現(xiàn)“原價(jià)”、“等級(jí)”和“折扣”比較可疑。通過(guò)對(duì)前面材料的回顧分析,基本可以肯定“原價(jià)”應(yīng)為物料的一個(gè)屬性,難以成為單獨(dú)的實(shí)體,排除。而“折扣”和“等級(jí)”是否能成為實(shí)體,依賴(lài)于后續(xù)系統(tǒng)的設(shè)計(jì)方式,如果將等級(jí)單獨(dú)設(shè)計(jì)成一個(gè)模塊,則其應(yīng)該為一個(gè)實(shí)體,而若將其設(shè)計(jì)為加盟商的屬性,則不能成為實(shí)體。對(duì)于這種摸棱兩可的候選項(xiàng),我們姑且保留,并加一個(gè)“?”作為后綴。當(dāng)然,由于前面分析中說(shuō)明“折扣關(guān)聯(lián)與等級(jí)”,所以,僅保留“等級(jí)”就可以了,“折扣”可作為其屬性。

經(jīng)過(guò)上述篩選,獲得下列領(lǐng)域?qū)嶓w:加盟商,連鎖店,管理員,直屬連鎖店,等級(jí)?。

我們不妨先將各個(gè)實(shí)體畫(huà)入領(lǐng)域分析圖。

step3、確定實(shí)體間的關(guān)系

有了實(shí)體,下面要確定各個(gè)實(shí)體間的關(guān)系。如上圖所示,管理員比較容易確定,因?yàn)樗坪醪慌c任何實(shí)體存在靜態(tài)關(guān)系。這里比較糾結(jié)的是加盟商、連鎖店、直屬連鎖店和等級(jí)四個(gè)實(shí)體。關(guān)于它們間的關(guān)系我們不能臆想,要去查閱前面的記錄資料或去咨詢(xún)客戶(hù)。在OOA&D實(shí)踐之路——真實(shí)案例解析OO理論與實(shí)踐(三、降低風(fēng)險(xiǎn))一文中,我們記錄了這樣一段文字:

“加盟商和連鎖店不是一個(gè)概念,加盟商直屬總公司,連鎖店可能直屬總公司也可能直屬某加盟商。加盟商和直屬總公司的連鎖店直接向總公司定料,不直屬的的連鎖店向相應(yīng)加盟商領(lǐng)取原料。連鎖店按原價(jià)定料,加盟商按照等級(jí)分為5級(jí),每級(jí)折扣不同。”

從以上文字中,我們提煉出如下關(guān)系:

1)加盟商和連鎖店沒(méi)有關(guān)系。

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

3)非直屬連鎖店可能會(huì)屬于某個(gè)加盟商。

4)等級(jí)僅屬于加盟商。

到這里為止,幾個(gè)實(shí)體間的關(guān)系基本清晰了,我們將其表達(dá)在領(lǐng)域分析圖里:

以上就是第一輪迭代的領(lǐng)域分析圖了。其中直屬連鎖店和非直屬連鎖店都繼承于連鎖店,而非直屬連鎖店必定對(duì)應(yīng)一個(gè)加盟商,加盟商可以對(duì)應(yīng)零到多個(gè)非直屬連鎖店,每個(gè)加盟商有且只有一個(gè)對(duì)應(yīng)的等級(jí)。

step4、領(lǐng)域分析的優(yōu)化

別覺(jué)得完成上述步驟就萬(wàn)事大吉了,雖然我們的領(lǐng)域分析模型已經(jīng)出來(lái)了,但它可靠嗎?還有優(yōu)化的余地嗎?萬(wàn)事多思考一點(diǎn),總是沒(méi)壞處的。就像剛出廠沒(méi)經(jīng)過(guò)檢測(cè)的飛機(jī),你敢坐嗎?所以,這里我們要對(duì)已經(jīng)成型的領(lǐng)域分析模型進(jìn)行一個(gè)檢測(cè)。檢測(cè)的方法很簡(jiǎn)單,就是回顧前述工作,逐個(gè)點(diǎn)進(jìn)行驗(yàn)證和確認(rèn)。當(dāng)我回顧了特性及初步業(yè)務(wù)需求后,發(fā)現(xiàn)如下兩點(diǎn)問(wèn)題:

第一、管理員是否是領(lǐng)域中的實(shí)體?要知道,領(lǐng)域中的實(shí)體,一定是系統(tǒng)邊界內(nèi)的實(shí)體。那這里就要分情況討論了,如果系統(tǒng)只需要一個(gè)管理員,那么系統(tǒng)中就沒(méi)有對(duì)管理員的管理,那么管理員只是系統(tǒng)外部的用戶(hù),就不能存在于領(lǐng)域?qū)嶓w中了;如果有多個(gè)管理員,并且管理員管理單獨(dú)成為一個(gè)模塊,則管理員應(yīng)放在這里。于是我聯(lián)系了客戶(hù),在確認(rèn)系統(tǒng)只需要一個(gè)管理員后,我毫不猶豫將管理員從領(lǐng)域模型中抹去了。

第二、我覺(jué)得領(lǐng)域模型抽象層次還有所欠缺。加盟商和連鎖店性質(zhì)很類(lèi)似,都有注冊(cè)、都要被審核,其實(shí)它們應(yīng)該繼承自某個(gè)更高抽象,這里我稱(chēng)其為會(huì)員。于是經(jīng)過(guò)思考和修正,得到最終的領(lǐng)域模型如下:

這里要注意,領(lǐng)域模型只表示出實(shí)體和實(shí)體間的靜態(tài)關(guān)系就好了。至于各個(gè)實(shí)體有哪些屬性,有哪些交互,那是后面設(shè)計(jì)階段的工作。

基于用例的需求分析——編寫(xiě)用例圖及用例規(guī)約

傳統(tǒng)的軟件工程中,通常使用需求規(guī)格說(shuō)明書(shū)進(jìn)行系統(tǒng)需求分析。而我更喜歡使用用例分析技術(shù)。在用例分析階段,我們要輸出兩份文檔:用例圖和用例規(guī)約。用例圖用于概觀上描述需求,用例規(guī)約用于對(duì)用例的流程進(jìn)行詳細(xì)描述,直接作為后續(xù)設(shè)計(jì)、編碼及測(cè)試的依據(jù)。

下面進(jìn)行系統(tǒng)需求分析。

step1、提取特性中的動(dòng)詞

上面我們?cè)褂锰崛∶~法找實(shí)體,那么要找用例,就要分析特性中的動(dòng)詞了。廢話不多說(shuō),我們先提取出特性3、4和6中的動(dòng)詞:注冊(cè),審核,使用,管理,定料。因?yàn)橛美治鲋幸_定每個(gè)用例的Actor,所以,在提取完動(dòng)詞后,要對(duì)每個(gè)動(dòng)詞賦予其主語(yǔ),作為其Actor,于是,最終得到的提取列表如下:注冊(cè)【未注冊(cè)加盟商和連鎖店】,審核【管理員】,使用【注冊(cè)后的加盟商和連鎖店】,管理【管理員】,定料【注冊(cè)后的加盟商和連鎖店】。

step2、動(dòng)詞篩選

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

step3、用例分析與優(yōu)化

這里的用例有進(jìn)一步分析的余地,首先,“管理”這個(gè)用例粒度太大,很難知道設(shè)計(jì)和開(kāi)發(fā),于是應(yīng)進(jìn)行分解;其次,“審核”應(yīng)屬于管理的一部分。基于以上兩點(diǎn),將管理分解為“刪除會(huì)員”、“指定加盟商等級(jí)”和“審核會(huì)員”,另外,“未注冊(cè)的加盟商和連鎖店”,跟據(jù)領(lǐng)域分析,可寫(xiě)作“未注冊(cè)會(huì)員”。另外,這里有幾個(gè)隱含的用例,就是關(guān)于等級(jí)的管理,這幾個(gè)用例從動(dòng)詞分析中是提取不出來(lái)了,這取決于特性描述的局限性。我們通過(guò)經(jīng)驗(yàn)和個(gè)人的分析,得到關(guān)于等級(jí)的管理用例。于是,最終用例敲定如下(這里用例命名規(guī)則為 uc迭代周期編號(hào).用例編號(hào)):

uc1.1 - 注冊(cè) actor:未注冊(cè)會(huì)員

uc1.2 - 刪除會(huì)員 actor:管理員

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

uc1.4 - 審核會(huì)員 actor:管理員

uc1.5 - 添加等級(jí) actor:管理員

uc1.6 - 刪除等級(jí) actor:管理員

uc1.7 - 等級(jí)信息維護(hù) actor:管理員

step4、給出用例圖

跟據(jù)上述分析,給出用例圖如下:

step4、編寫(xiě)用例規(guī)約

需求分析的最后一步,就是為每個(gè)用例編寫(xiě)相應(yīng)的用例規(guī)約。用例規(guī)約是一種規(guī)范化文檔,它面向設(shè)計(jì)開(kāi)發(fā)人員,詳細(xì)描述了各個(gè)用例內(nèi)部的基本信息、執(zhí)行流程及例外流程等,必要時(shí)可附上相應(yīng)的活動(dòng)圖。因?yàn)橛美?guī)約是設(shè)計(jì)和開(kāi)發(fā)的重要參考文檔,所以在編寫(xiě)過(guò)程中務(wù)必要做到詳盡和準(zhǔn)確。

下面僅給出“注冊(cè)”這個(gè)用例的用例規(guī)約作為示例和參考。

必要時(shí),可在下端附上活動(dòng)圖:

總結(jié)

在每個(gè)迭代周期的初始階段,當(dāng)選擇完需要迭代的特性后,就可以開(kāi)始領(lǐng)域分析和需求分析了。本文是先進(jìn)行領(lǐng)域分析。其實(shí)兩者并無(wú)確定的先后順序,往往是相輔相成,交叉進(jìn)行。下一篇文章將進(jìn)入第一迭代周期的設(shè)計(jì)階段。

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

本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁(yè)面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。

責(zé)任編輯:

標(biāo)簽:

相關(guān)推薦:

精彩放送:

新聞聚焦
Top 主站蜘蛛池模板: 九龙坡区| 兰西县| 郓城县| 赤峰市| 铁岭县| 清流县| 乐山市| 芦山县| 嵊州市| 苍山县| 二手房| 宾川县| 宁津县| 霸州市| 手机| 东乌珠穆沁旗| 于田县| 从江县| 金平| 隆回县| 奇台县| 沽源县| 岫岩| 郑州市| 嵊泗县| 许昌市| 成安县| 海晏县| 黄陵县| 乡城县| 乌海市| 兰考县| 左贡县| 饶平县| 靖宇县| 遂平县| 璧山县| 施甸县| 桑植县| 无棣县| 镇沅|