前言
因?yàn)橹耙恢碧幵谟螒蜷_發(fā)行業(yè),由于種種原因一直對軟件工程中的項(xiàng)目管理、項(xiàng)目開發(fā)方法缺乏體驗(yàn)。雖然項(xiàng)目中也曾倡導(dǎo)編寫更多的文檔,無論是模塊說明文檔還是設(shè)計(jì)文檔,但效果一直不好。不甚理想的地方主要體現(xiàn)在文檔的規(guī)范性欠缺、不統(tǒng)一、浮于表面沒有實(shí)質(zhì)內(nèi)容。文檔的編寫缺乏詳盡的方法指導(dǎo),那么所謂的設(shè)計(jì)文檔要么是用來敷衍上級要么就是隨著開發(fā)人員的水平不一而千差萬別。
當(dāng)我開始目前這個非游戲項(xiàng)目時,我也曾想,前期做好結(jié)構(gòu)設(shè)計(jì),制定好關(guān)鍵問題的解決方案,那么要完成這個項(xiàng)目就不在話下了。但是我很快就面臨了一個問題:需求不定?;叵肷硖幱螒蚬镜哪切┤兆?,程序員總是抱怨策劃需求變更過快過多,在每一次策劃提出一個需求變更時,謹(jǐn)慎的程序員都會再三讓策劃保證:放心,不會變了。而我面臨的問題則更為嚴(yán)峻。我意識到,項(xiàng)目的需求,就連用戶也無法一一羅列出來。我們需要的是需求調(diào)研。但就算你將客戶的所有需求全部挖掘出來后(這幾乎不可能,因?yàn)樗麄冏约阂膊惶宄约合胍裁矗?dāng)你交付了第一個軟件版本,幾乎可以肯定客戶會提出一大堆的需求變更:我要的不是這個,我要的那個怎么沒有,哦,我當(dāng)初以為你說的是另一個意思。
當(dāng)然,需求調(diào)研這種工作不是讓程序員去做的(那會更悲劇,無論是對客戶還是對程序員而言,他們都是在對牛彈琴)。但需求的不確定性也總是存在的。
事實(shí)上,需求變化本身就是一個很正常的現(xiàn)象。我一向愿意更悲觀地處理軟件開發(fā)方面的問題,所謂小心使得萬年船?;诖耍覜Q定擺好心態(tài)學(xué)學(xué)軟件開發(fā)的方法學(xué)。
概要
本文簡要描述、總結(jié)了RUP開發(fā)方法學(xué)的主要內(nèi)容,結(jié)合我自己的感受闡述了一些RUP的核心原則。我相信我所理解的內(nèi)容是膚淺的,對于非代碼的表達(dá)我更相信其是存在歧義的。所以本文僅當(dāng)是一種經(jīng)驗(yàn)參考,不必當(dāng)真。
RUP據(jù)傳是用于指導(dǎo)大型甚至超大型項(xiàng)目開發(fā)的,我們做的不是這樣規(guī)模的項(xiàng)目。但是我們需要記錄下整個項(xiàng)目的開發(fā)過程,通過這個過程中產(chǎn)出的工件任何一個人可以看出這個項(xiàng)目是如何實(shí)現(xiàn)出來的,其目的在于規(guī)避唯有從海量代碼中才能熟悉項(xiàng)目實(shí)現(xiàn)這種問題。這里出現(xiàn)了一個概念:工件,其指的是軟件項(xiàng)目開發(fā)過程中任何留下記錄的事物,例如文檔、圖、代碼等。RUP的一個重要思想,在于其整個軟件開發(fā)過程都是可推導(dǎo)的。例如我們通常說的軟件架構(gòu),或小一點(diǎn)的模塊結(jié)構(gòu),都是通過開發(fā)過程中前面階段產(chǎn)出的工件推導(dǎo)得出,而不是憑借程序員的經(jīng)驗(yàn)拍腦袋想出來的(經(jīng)驗(yàn)不太可靠,并且千差萬別,而推導(dǎo)意味著將每個環(huán)節(jié)變得可靠)。我們借助RUP的這個特性,創(chuàng)建這些工件,用以建立起軟件實(shí)現(xiàn)的可靠知識庫。
RUP概覽
以下均摘自<Thinking in UML>中對RUP的描述:
統(tǒng)一過程歸納和集成了軟件開發(fā)活動中的最佳實(shí)踐,它定義了軟件開發(fā)過程中最重要的階段和工作(四個階段和九個核心工作流),定義了參與軟件開發(fā)過程的各種角色和他們的職責(zé),還定義了軟件生產(chǎn)過程中產(chǎn)生的工件,并提供了模板。最后,采用演進(jìn)式軟件生命周期(迭代)將工作、角色和工件串在一起,形成了統(tǒng)一過程。
統(tǒng)一過程是一種追求穩(wěn)定的軟件方法,它追求開發(fā)穩(wěn)定架構(gòu),控制變更
統(tǒng)一過程集成了面向?qū)ο蠓椒?、UML語言、核心工作流、工件模板和過程指導(dǎo)等知識
簡單來說,RUP作為一種軟件項(xiàng)目開發(fā)方法學(xué),它定義了軟件開發(fā)的每一個過程,最重要的是它指導(dǎo)了在每一個過程需要產(chǎn)出什么,這些產(chǎn)出又是怎樣得到。它試圖規(guī)范化整個流程,以規(guī)避需求變更,項(xiàng)目參與者水平不一等帶來的項(xiàng)目不可控等問題,以期一個軟件產(chǎn)品穩(wěn)定地開發(fā)出來。在一個項(xiàng)目開發(fā)過程中,最核心的資源是人,最不可控的亦是人。
RUP過程與實(shí)踐
我覺得要快速學(xué)習(xí)一種知識,需要首先獲得這門知識的總體框架。另一方面,在我們獲得更多信息后,我們需要挖掘出這門知識的核心思想。學(xué)習(xí)RUP我覺得從這兩方面入手是相對比較快速和有效的手段。
RUP框架
RUP定義了軟件開發(fā)過程的四個階段,以及9個工作流程。一張極為經(jīng)典的RUP開發(fā)過程框架圖如下:

RUP將整個軟件開發(fā)過程分為四個階段:
- 先啟(Inception)、
- 精化(Elaboration)
- 構(gòu)建(Construction)
- 產(chǎn)品化(Transition)
每一個階段的工作分為9個流程:
- 業(yè)務(wù)建模
- 需求
- 分析設(shè)計(jì)
- 實(shí)施
- 測試
- 部署
- 配置與變更管理
- 項(xiàng)目管理
- 環(huán)境
其中,前6個流程被統(tǒng)稱為”engineering disciplines”,后3個流程被稱為”supporting disciplines”。當(dāng)然,我們主要關(guān)注前6個流程。那么,這些工作流程和開發(fā)階段又有什么關(guān)系呢?上圖中其實(shí)已經(jīng)闡明了這些關(guān)系。
RUP指導(dǎo)迭代開發(fā)。在軟件開發(fā)的這4個階段中,每一個階段會被分為若干次迭代。而每一次迭代則涵蓋了這9個工作流程。隨著開發(fā)階段向產(chǎn)品化靠近,自然而然地,需求的變更、增加自然會減少,所以從圖中可以看出,開發(fā)過程越到后期,其工作流程中關(guān)于需求的工作則越少。同樣,在先啟階段,其需求相關(guān)的工作則占據(jù)了該階段的主要工作內(nèi)容。
RUP中的迭代要求在每一次迭代中,都會完整地實(shí)施一遍整個工作流程。在軟件實(shí)施階段,甚至?xí)诿恳粋€迭代過程完后輸出一個可運(yùn)行的軟件版本。這個版本可能會被交付給客戶,以期進(jìn)一步地在功能需求上取得與客戶一致的意見。這倒是同敏捷開發(fā)有點(diǎn)類似。
既然制定了工作流程,那每一個工作流程該如何去實(shí)施呢?RUP制定了每個工作流程需要參與的角色,這些角色需要從事的活動,以及這些活動產(chǎn)生的工件。
這句話實(shí)際上反映了RUP的一個重要信息,摘自wiki:
RUP is based on a set of building blocks, or content elements, describing what is to be produced, the necessary skills required and the step-by-step explanation describing how specific development goals are to be achieved. The main building blocks, or content elements, are the following:
- Roles (who) – A Role defines a set of related skills, competencies and responsibilities.
- Work Products (what) – A Work Product represents something resulting from a task, including all the documents and models produced while working through the process.
- Tasks (how) – A Task describes a unit of work assigned to a Role that provides a meaningful result.
RUP建模
在我看來,RUP每個工作流程所完成的工作,就是一個建模的過程。所謂建模,簡單來說就是將需要描述的事物通過更系統(tǒng)的形式表達(dá)出來,以期獲得對該事物更深入的理解。<Thinking in UML>中定義建模概念為:
建模(modeling),是指通過對客觀事物建立一種抽象的方法用以表征事物并獲得對事物本身的理解,同時把這種理解概念化,將這些邏輯概念組織起來,構(gòu)成一種對所觀察的對象的內(nèi)部結(jié)構(gòu)和工作原理的便于理解的表達(dá)。
在這里,建模的過程需要使用一些工具。在RUP中建模使用UML來完成。在<Thinking in UML>中講述了UML的核心模型,包括:
- 業(yè)務(wù)用例模型
- 概念用例模型
- 系統(tǒng)用例模型
- 領(lǐng)域模型
- 分析模型
- 軟件架構(gòu)和框架
- 設(shè)計(jì)模型
- 組件模型
- 實(shí)施模型
可能在大家的普遍認(rèn)識中,UML無非就是幾種圖,并且粗看一眼理解起來也不困難,甚至還能用來畫畫類圖做下代碼結(jié)構(gòu)設(shè)計(jì)。但UML的作用不僅僅如此。
以上所描述的UML核心模型中,每個模型并不單指的的是一種UML圖。每個模型實(shí)際上都會包含幾種UML圖,會包含若干張UML圖。這些模型基本上滲透于RUP的9個工作流程中,只不過不同的工作流程使用的模型比重不一而已。
例如在“分析設(shè)計(jì)”工作流程中,可能會使用到系統(tǒng)用例模型、分析模型、軟件架構(gòu)和框架、設(shè)計(jì)模型等,而業(yè)務(wù)用例模型可能在這個流程中根本不會用到;相反,業(yè)務(wù)用例模型則可能在“業(yè)務(wù)建?!绷鞒讨斜粡V泛使用。
前已述及在RUP的每個工作流程中,RUP定義了該流程需要參與的角色,以及這些角色需要進(jìn)行的活動,例如這里可以看看“分析設(shè)計(jì)”流程中的角色和活動集(摘自<Thinking in UML>):

相應(yīng)的,在該工作流程中需要產(chǎn)出的工件集為(摘自<Thinking in UML>):

既然使用了UML作為建模工具,所以可以簡單地說這些工件主要就是UML圖,當(dāng)然也會有其他文檔性質(zhì)的事物,例如網(wǎng)絡(luò)協(xié)議結(jié)構(gòu)、數(shù)據(jù)庫表等UML無法描述的東西則通過普通文字性文檔描述。
RUP最佳實(shí)踐
到目前為止我們已經(jīng)了解到RUP定義了開發(fā)過程(phase),定義了每個過程包含的若干工作流程,還定義了每個工作流程需要哪些角色從事哪些活動來完成哪些工件。除此之外,RUP還提供了6條最佳實(shí)踐用以指導(dǎo)軟件開發(fā):
- 迭代開發(fā)
- 管理需求
- 使用基于組件的架構(gòu)
- 可視建模
- 持續(xù)的質(zhì)量驗(yàn)證
- 控制變更
這些實(shí)踐在我看來僅僅是一些項(xiàng)目開發(fā)的指導(dǎo)原則,它們滲透到每一個過程,每一個工作流程。在項(xiàng)目過程中實(shí)踐這些原則,用以確保項(xiàng)目的成功。例如我們使用UML建模,以達(dá)到“可視建模”。我們通過建立需求用例,以“管理需求”。
RUP核心思想
似乎沒有文檔來專門闡述RUP的核心思想,但我覺得掌握其核心思想才是學(xué)習(xí)的要點(diǎn)所在。要理解一種軟件開發(fā)方法學(xué)的核心思想,其實(shí)最好是將其與別的方法學(xué)做比較。這里先就我的一些感想做闡述。
用例驅(qū)動
用例驅(qū)動指的是整個軟件項(xiàng)目的推進(jìn)過程,是依靠“用例”來完成。<Thinking in UML>:
在實(shí)際的軟件項(xiàng)目中,一個軟件要實(shí)現(xiàn)的功能通過用例來捕獲,接下來的所有分析、設(shè)計(jì)、實(shí)現(xiàn)、測試都由用例來取得,即以實(shí)現(xiàn)用例為目標(biāo)。在統(tǒng)一過程中用例能夠驅(qū)動的不僅僅是分析設(shè)計(jì)。
用例簡單來說就是描述了一個系統(tǒng)功能。但必須注意的是,這僅僅是它定義的一小部分。用例主要分布在“業(yè)務(wù)建?!薄ⅰ靶枨蟆?、“分析設(shè)計(jì)”這些工作過程中。在不同的過程中用例的粒度和性質(zhì)都不一樣。例如對于一個借書系統(tǒng)而言,在業(yè)務(wù)建模階段,我們可以獲取出一個“借書”用例,其系統(tǒng)邊界甚至不是系統(tǒng)而可能僅關(guān)注這個業(yè)務(wù)本身(因?yàn)檫@個階段還沒有考慮到計(jì)算機(jī)如何實(shí)現(xiàn)這個借書業(yè)務(wù));在系統(tǒng)分析階段,我們就可以將“借書”這個用例細(xì)化為用戶和計(jì)算機(jī)軟件系統(tǒng)的交互;進(jìn)一步地,我們可能會進(jìn)一步精化這個用例,例如用戶通過網(wǎng)頁終端“借書”。(這里描述了很多建模的細(xì)節(jié),可不必深究,本文只給出一個概要性的介紹)
我們說用例驅(qū)動軟件開發(fā),但它如何驅(qū)動的呢?我在實(shí)際的建模過程中,最明顯的感受就是用例驅(qū)動了整個建模過程。
- 在需求分析階段,我以系統(tǒng)使用者的角度繪制出了一份用例圖,用于表達(dá)使用者對該系統(tǒng)的需求
- 然后我繪制序列圖(活動圖等)來實(shí)現(xiàn)這些用例,也就是闡述使用者具體是如何與系統(tǒng)交互的
- 從之前的建模過程中我獲得對系統(tǒng)功能需求方面的認(rèn)識
- 基于前面的分析我可以繪制出系統(tǒng)用例圖,以明確系統(tǒng)的各個功能需求
- 同樣針對用例繪制用例實(shí)現(xiàn)圖
- 用例本身應(yīng)該包含更多的文檔,因此我編寫用例規(guī)約用以詳細(xì)描述各個用例
- 從用例規(guī)約、用例實(shí)現(xiàn)中我可以抽離出一些分析類(較設(shè)計(jì)類更高抽象的類),包含用例場景中涉及到的實(shí)體,控制邏輯
- 細(xì)化這些分析類,將分析類組織起來形成系統(tǒng),我會用界面類去銜接各個控制類
- 將得到的分析類按模塊來劃分,從而可以得到一個初步的系統(tǒng)架構(gòu)
- 初步考慮系統(tǒng)實(shí)現(xiàn),我甚至?xí)玫揭粋€初步是的系統(tǒng)部署圖
- 回過頭不斷審視系統(tǒng)用例,以確認(rèn)我是否實(shí)現(xiàn)了所有用例,這可以保證我的分析實(shí)現(xiàn)了所有需求,我不用枚舉所有系統(tǒng)特性是否被我考慮周全,我僅需在已有用例圖中核實(shí)
- 基于模塊實(shí)現(xiàn)各個用例,或者基于分析類來實(shí)現(xiàn)系統(tǒng)用例
- 通過重新繪制以及核實(shí)用例,可以進(jìn)一步精化分析類,分析類在很大程度上會一一對應(yīng)到設(shè)計(jì)類,而設(shè)計(jì)類則對應(yīng)到實(shí)際的代碼
- 可以進(jìn)入設(shè)計(jì)階段,設(shè)計(jì)階段會考慮到系統(tǒng)的實(shí)現(xiàn)細(xì)節(jié),例如使用的語言,使用的框架等
進(jìn)入設(shè)計(jì)階段后,雖然可以進(jìn)一步建模,得到會直接映射到代碼的類圖、序列圖等,但這樣的圖在面臨需求變更時,基本上會面臨修改,這意味著維護(hù)這些文檔需要耗費(fèi)精力。所以,<Thinking in UML>中主張將精力放在維護(hù)分析類模型中,而通過其他約定實(shí)現(xiàn)從分析類到實(shí)際代碼的轉(zhuǎn)換。我覺得這個也在理。
規(guī)范化整個過程
我個人覺得RUP的一大特點(diǎn)在于規(guī)范化了整個軟件開發(fā)過程,每一個步驟需要哪些角色參與,該干什么,怎么去干都有指導(dǎo)。加之這些活動的”可推導(dǎo)性“,這意味著不論參與角色屬于什么水平,都可以穩(wěn)固地推進(jìn)項(xiàng)目進(jìn)程。
此外,這種規(guī)范化也會給項(xiàng)目留下詳細(xì)的演化過程。你可以明確地看到整個軟件是如何演化出最終的產(chǎn)品代碼,可以深入地理解項(xiàng)目代碼中的設(shè)計(jì)。
總結(jié)
我只是一個RUP新手,即便如此,我依然不覺得RUP是軟件開發(fā)的萬能藥。我相信任何軟件開發(fā)方法都是有局限性的。我們在實(shí)際使用的時候也只是吸取其精華。不同的開發(fā)方法其適用范圍也是不一樣的。正如有人將RUP和XP做比較時說,如果你使用RUP去開一個雜貨鋪,在沒開張之前你就已經(jīng)破產(chǎn)了;同樣如果你用XP去做飛機(jī),飛機(jī)毀了十來次也許才能做出來(from <Thinking in UML> again)。