也許由于軟件行業(yè)固有的“高科技”特性(或者說,,軟件人固有的顧影自憐),,軟件項(xiàng)目的管理和過程控制中從來就不缺少形形色色的工具。在一些大型的,、“正規(guī)的”軟件企業(yè)中,,配置管理要通過ClearCase,軟件設(shè)計(jì)要使用Rose畫出一大堆精美的圖形,,壓力測(cè)試要用LoadRunner來跑……當(dāng)軟件公司的老板們癡迷于“形式化管理”與漂亮的報(bào)表和文檔時(shí),,這些昂貴的商業(yè)工具著實(shí)在他們那里得到了不少的青睞。 幸運(yùn)的是,,越來越多的軟件開發(fā)者和老板開始意識(shí)到,,軟件項(xiàng)目采用的方法沒有一定之規(guī),不同的項(xiàng)目,、不同的團(tuán)隊(duì)需要選擇不同的開發(fā)方法,。而工具,則如同三棱鏡般折射出方法學(xué)的身影——用著微軟的TeamSystem就很難不遵循微軟推薦的最佳實(shí)踐,,同樣RUP在沒有Rational工具支持的情況下也難以實(shí)施,。于是,選擇開發(fā)過程工具,,很大程度上就成了選擇開發(fā)方法的一個(gè)副產(chǎn)品,。 對(duì)于身處激烈需求變更風(fēng)暴之中的企業(yè)應(yīng)用開發(fā)者,如何步步緊跟客戶的真實(shí)需求,、如何確保時(shí)刻為客戶提供最大價(jià)值是他們每天冥思苦想的問題,。此時(shí)注重交流反饋、以客戶價(jià)值為驅(qū)動(dòng)的各種敏捷開發(fā)方法就成為了他們自然而然的選擇,。而有趣的是,,開源的過程工具也大多與敏捷方法最為適應(yīng)??此婆既?,其實(shí)卻有其道理:開源項(xiàng)目更少受到種種政治因素的影響,,生存的環(huán)境又有更多的不確定性,因此也更加強(qiáng)調(diào)時(shí)刻保證最大化的客戶價(jià)值,。而這種思路,,與敏捷方法是不謀而合的。再加上,,推崇敏捷方法的那些“實(shí)用主義程序員”們往往也正是開源社群的積極分子,,所以適用于敏捷項(xiàng)目的開源過程工具尤其容易找到也就不足為奇了。 敏捷的開發(fā)者們是幸福的,,因?yàn)樗麄儞碛斜姸鄡?yōu)秀的開源工具可供選擇,;敏捷的開發(fā)者們又是痛苦的,因?yàn)樗麄儽仨氃趤y花漸欲迷人眼的工具叢中找出適合自己的一組工具棧,,并將它們與自己的管理策略糅合成一個(gè)完整的開發(fā)過程,。本文將為讀者介紹ThoughtWorks公司常用的一組過程工具,以及在敏捷項(xiàng)目中使用這些工具的些許經(jīng)驗(yàn),,希望能幫助讀者略微緩解這種痛苦,。 作為一個(gè)程序員,筆者對(duì)過程工具的關(guān)注也更多地集中在技術(shù)層面上,。從我的角度看來,,敏捷方法最為重要、也最立竿見影的部分當(dāng)屬測(cè)試驅(qū)動(dòng)與持續(xù)集成,,我們的工具之旅就從這兩件事情開始,。 單元測(cè)試:JUnit(以及mock)在敏捷開發(fā)的工具箱里,JUnit很可能是最廣為人知,、也最受到重視的一個(gè),,當(dāng)然它也當(dāng)?shù)闷疬@樣的殊榮。若論出身,,JUnit是由Kent Beck與Erich Gamma兩人共同創(chuàng)造的,。若論影響,由它引入的“紅條/綠條”更是影響深遠(yuǎn),。 圖1:各種各樣的Green Bars “紅條/綠條”不僅僅是一個(gè)測(cè)試成功與失敗的標(biāo)記,,它們構(gòu)成了敏捷開發(fā)中最基本的韻律:“編寫測(cè)試 – 紅條 – 編寫代碼 – 綠條 – 重構(gòu)”,這五個(gè)簡(jiǎn)單的步驟確保了每一個(gè)思緒都有單元測(cè)試作為記錄,,每一段代碼都有單元測(cè)試保證它的質(zhì)量,,整個(gè)軟件項(xiàng)目始終朝著價(jià)值最大化、質(zhì)量最優(yōu)化的方向前進(jìn),。而紅條與綠條,,則清晰直觀地指出你當(dāng)前所在的位置,以及下一步應(yīng)該做的工作。一個(gè)醒目的紅條/綠條對(duì)于開發(fā)者的心理有著如此重要的暗示作用,,以至于當(dāng)微軟在Visual Studio 2005的單元測(cè)試工具中沒有放置這樣一個(gè)醒目的標(biāo)志時(shí),,竟引來了開發(fā)者的一片怨聲載道。 當(dāng)我說JUnit的時(shí)候,,我意指的是整個(gè)xUnit家族——覆蓋了從Java/.NET直到C/C++再到Haskell/Eiffel最后到JavaScript/Ruby/Python的大家族,。雖然運(yùn)行在不同平臺(tái)、不同語言,,它們擁有同一組無法錯(cuò)認(rèn)的特征:紅條/綠條,、TestCase/TestSuite……這也讓開發(fā)者們無論走到哪里總可以感到放心,。在開始編寫你的任何一段代碼之前,,先為它寫上一段測(cè)試;盡可能頻繁地運(yùn)行所有的測(cè)試,。你可以立刻感受到TDD帶來的幫助,。 不過還有一個(gè)催化劑可以讓這種化學(xué)變化來得更加強(qiáng)烈,那就是mock框架,。以EasyMock和JMock為代表的mock框架,,其作用是模擬被測(cè)對(duì)象之外的相關(guān)對(duì)象,從而實(shí)現(xiàn)對(duì)象之間的解耦合,,達(dá)到真正意義上的“單元測(cè)試”,。奇妙的是,當(dāng)你把mock框架放入測(cè)試驅(qū)動(dòng)實(shí)踐中時(shí),,開發(fā)過程就會(huì)引導(dǎo)著你得到低耦合,、模塊化的設(shè)計(jì),因?yàn)槟愫茈y為一組緊密耦合的類編寫測(cè)試,,而mock框架則讓你愿意采用IoC模式分離出更多的類來承擔(dān)各自的責(zé)任,。在.NET和Ruby等主要平臺(tái)上,也有類似的mock框架可供選擇,。 功能測(cè)試:Selenium拋開所有的技術(shù)考量,,單憑直覺來說,我個(gè)人認(rèn)為Selenium最大的優(yōu)點(diǎn)在于它的震撼性:成百上千個(gè)test case運(yùn)行起來,,只見web頁面不斷地在屏幕上閃過,,模擬著各種各樣的用戶操作,最后生成一張龐大的報(bào)表,,背景是令人平靜愉悅的淡綠色,。即便對(duì)于全然對(duì)于不懂技術(shù)的管理者或客戶,這一過程的心理效果也是不言而喻的,。 圖2:Selenium也采用了紅條/綠條的界面設(shè)計(jì) 在沒有使用Selenium之前,,很多人都認(rèn)為web界面是無法測(cè)試驅(qū)動(dòng)、也無需測(cè)試驅(qū)動(dòng)的。但此時(shí)我們就常常遇到這樣的困境:客戶認(rèn)為頁面上的一句話應(yīng)該這樣寫,,開發(fā)者卻認(rèn)為客戶三天前的意見是另一樣,,認(rèn)真回想起來卻又沒人能記得三天前到底說過什么。如果說JUnit單元測(cè)試記錄了開發(fā)者對(duì)于軟件的設(shè)計(jì)思路,,那么Selenium就記錄了客戶對(duì)于軟件功能的要求,,并時(shí)時(shí)驗(yàn)證客戶的要求仍然得到滿足。 Selenium的用法有很多種,。你可以把它放在構(gòu)建流程之外,,由客戶定期檢驗(yàn)軟件的功能是否符合需求;你也可以讓它作為構(gòu)建流程的一部分,,用它來驅(qū)動(dòng)功能的開發(fā),,形成一個(gè)更大范圍的“紅-綠-重構(gòu)”循環(huán)。除了編寫HTML格式的測(cè)試腳本之外,,Selenium還支持編程驅(qū)動(dòng)的模式,,可以用程序代碼來編寫可復(fù)用的測(cè)試案例。而且整個(gè)Selenium是用JavaScript和HTML編寫的,,這也就意味著你可以輕松地將其融入任何一個(gè)web應(yīng)用,,不管開發(fā)這個(gè)應(yīng)用的平臺(tái)是J2EE還是.NET或者Rails。 Selenium的名字還有一個(gè)有趣的由來:在Selenium出現(xiàn)之前,,最著名的web應(yīng)用功能測(cè)試工具當(dāng)屬Mercury Quanlity Center,,但那是一個(gè)商業(yè)工具,功能強(qiáng)大卻也價(jià)格不菲,,常常讓開發(fā)者們又愛又恨,。所以,自己動(dòng)手開發(fā)開源功能測(cè)試工具的ThoughtWorker們把這個(gè)工具叫做Selenium——“mercury”有“水銀”的意思,,而“selenium”(硒元素)恰好是專解汞中毒的特效藥,。 構(gòu)建腳本:Ant vs. Maven現(xiàn)在你已經(jīng)用JUnit記下了所有設(shè)計(jì)思路,也用Selenium記下了所有功能需求,。你還需要讓所有測(cè)試案例都能自動(dòng)運(yùn)行,,這樣才能頻繁地驗(yàn)證所有測(cè)試仍然順利通過。這時(shí)Ant就來到了你的手邊,。由Apache組織開發(fā),,又有多年的實(shí)踐檢驗(yàn),Ant已經(jīng)積累了大量實(shí)用的插件,,幾乎所有常用的任務(wù)都有對(duì)應(yīng)的插件可以完成,。而且在Ant腳本中可以直接調(diào)用Java類(.NET平臺(tái)下的NAnt更是可以直接在腳本中插入C#代碼),也就是說你實(shí)際上可以用Ant來做任何事,。 不過最通常的用法,,還是用Ant來完成整個(gè)構(gòu)建流程:從編譯源代碼,,到打包應(yīng)用,到部署服務(wù)器,,到初始化數(shù)據(jù)庫,,再到執(zhí)行測(cè)試并生成測(cè)試報(bào)告,只需要一個(gè)指令就可以全部完成,。類似的構(gòu)建工具在C/C++的世界里早已存在,,那就是著名的make,不過Ant來得更加簡(jiǎn)單易用而已,。 作為后起之秀的Maven比之Ant最大的優(yōu)勢(shì)在于它內(nèi)建了更多對(duì)J2EE項(xiàng)目(尤其是web項(xiàng)目)的支持,,以及更多項(xiàng)目管理相關(guān)的功能。像單元測(cè)試,、創(chuàng)建報(bào)表等在Ant中用插件實(shí)現(xiàn)的功能,,在Maven中都有內(nèi)建的支持。甚至很多開源項(xiàng)目的網(wǎng)站都是用Maven直接生成的,。但以筆者愚見,,Maven強(qiáng)大的功能更適合開源軟件這樣組織松散的項(xiàng)目,,對(duì)于一般的企業(yè)應(yīng)用Ant已經(jīng)足夠了,。 不過在進(jìn)入了Ruby/Rails的世界之后,筆者感覺Ant和Maven都有一個(gè)共同的缺陷:它們的構(gòu)建腳本都采用XML編寫,,因此代碼量相當(dāng)巨大,,并且也不易理解。相比之下,,Rake直接用Ruby來編寫構(gòu)建腳本,,反倒顯得更加簡(jiǎn)潔易用。也許相比于XML,,我們還需要找到另一種更適合描述“軟件構(gòu)建”這一任務(wù)的領(lǐng)域?qū)S谜Z言,。 版本控制:CVS vs. Subversion任何一個(gè)多人開發(fā)的項(xiàng)目都必須有版本控制系統(tǒng)——即便一個(gè)人開發(fā),也需要版本控制系統(tǒng)來提供備份和恢復(fù)的支持,。由于有全面的測(cè)試作為保障,,敏捷方法提倡采用“所有人擁有所有代碼”的代碼所有權(quán)形式,這也就意味著時(shí)常會(huì)出現(xiàn)兩個(gè)人同時(shí)修改一份文件的情況,,在一些配置文件上這種情況出現(xiàn)得更加頻繁,。因此,敏捷開發(fā)所使用的版本控制系統(tǒng)最好不要采用文件級(jí)的鎖定——這正是VSS缺省的鎖定方式,,不過我們也可以通過配置來改變鎖定方式,。而開源的選擇,則是CVS與Subversion(簡(jiǎn)稱SVN),。 CVS與SVN存在著一些差異,,不過作為開發(fā)者的我們通常不必介意這些區(qū)別。值得注意的一點(diǎn)是,當(dāng)出現(xiàn)文件沖突時(shí),,SVN會(huì)強(qiáng)迫用戶首先消解沖突,,然后才能將文件提交到代碼庫。另外,,每當(dāng)有人成功提交新文件之后,,SVN會(huì)為整個(gè)項(xiàng)目生成一個(gè)新的修訂版本(revision),而不是像CVS那樣為每個(gè)文件單獨(dú)記錄修訂版本,,這也讓版本控制變得更加容易,。 在一個(gè)敏捷項(xiàng)目中,每個(gè)開發(fā)pair每隔15分鐘到半小時(shí)(最多不超過1小時(shí))就會(huì)提交自己最新的代碼,,一個(gè)項(xiàng)目組每天通常會(huì)生成數(shù)十個(gè)修訂版本,。即便不算其中無法成功構(gòu)建的版本,通常每周也能收獲上百個(gè)構(gòu)建版本,。察看每個(gè)構(gòu)建版本對(duì)應(yīng)的報(bào)表,,就是項(xiàng)目管理者有效掌握項(xiàng)目進(jìn)度的最佳途徑。 持續(xù)集成:CruiseControl我們剛才已經(jīng)提到,,在開發(fā)者不斷提交的修訂版本中,,有一部分是無法成功構(gòu)建的,原因就是在版本控制系統(tǒng)上運(yùn)行著一個(gè)忠實(shí)的看門人:持續(xù)集成工具,。它們的代表就是由ThoughtWorks員工開發(fā)和維護(hù)的CruiseControl,。 CruiseControl的任務(wù)非常簡(jiǎn)單:每當(dāng)有人提交了新的文件到代碼庫,它就把整個(gè)項(xiàng)目簽出(check-out)到一個(gè)測(cè)試環(huán)境,,然后執(zhí)行項(xiàng)目的構(gòu)建腳本,,完成整個(gè)構(gòu)建流程,并運(yùn)行所有測(cè)試,。如果這一切都順利通過,,CruiseControl就會(huì)生成一個(gè)新的構(gòu)建版本;否則,,構(gòu)建失敗,,所有人都不允許再簽出或提交任何代碼,直到造成破壞失敗的人把問題解決掉,,讓構(gòu)建重新成功為止,。 一個(gè)能夠成功構(gòu)建的代碼庫代表著項(xiàng)目的健康。保持項(xiàng)目健康是如此重要,,因此CruiseControl必須以最引人注目的方式告訴整個(gè)團(tuán)隊(duì):我們的項(xiàng)目現(xiàn)在怎么樣了,。為此,各個(gè)團(tuán)隊(duì)想出了種種辦法,。我們可以用一個(gè)客戶端工具來監(jiān)控CruiseControl的構(gòu)建情況,,然后讓這個(gè)客戶端在發(fā)現(xiàn)構(gòu)建失敗時(shí)調(diào)用別的程序:唱一段歌,,發(fā)出怪叫,或者點(diǎn)亮一盞燈……總之,,讓大家都知道,。 圖3:紅燈/綠燈,構(gòu)建結(jié)果一目了然 知識(shí)共享:Wiki,,尤其是TiddlyWiki“敏捷宣言”中清楚地寫著:“個(gè)體與交互勝于過程與工具”,。對(duì)于一個(gè)敏捷團(tuán)隊(duì)來說,最重要的事情莫過于建立有效的交流渠道,。在ThoughtWorks,,每個(gè)項(xiàng)目都有自己的wiki,開發(fā)者,、項(xiàng)目經(jīng)理,、客戶……所有的項(xiàng)目涉眾都會(huì)把自己的收獲與心得記錄在wiki上,以便大家分享和交流,。 開源的wiki很容易找到,,我在這里不必多說。我唯一想要介紹的,,是這個(gè)叫做TiddlyWiki的小東西,。這是一個(gè)完全用HTML和JavaScript編寫的wiki,使用它甚至不需要服務(wù)器,,你只要在本地打開這個(gè)HTML文件,,就可以開始寫你的wiki了,。你所寫的內(nèi)容同樣會(huì)被保存在這個(gè)HTML文件中,,并且還提供了修改跟蹤的能力。使用這個(gè)wiki,,你可以把整個(gè)文檔放到你的版本控制系統(tǒng)中,,不需要為它做任何額外的配置。 另外,,別忘了一個(gè)最重要的工具:紙卡片——你可以隨便寫,,用任何顏色寫,可以畫任何你想畫的圖,,可以用任何順序來排列粘貼它們,,可以任意移動(dòng),可以隨時(shí)加上注釋,,誰都知道怎么使用它們,。你甚至還可以撕掉它們,優(yōu)質(zhì)的紙卡片撕起來有一種特別的手感……好吧,,紙卡片不是軟件,,通常也不免費(fèi),,但你知道怎么得到它們。 圖4:ThoughtWorks——值得信賴的全球紙卡片提供商 寫在最后介紹了我們常用的工具之后,,相信讀者已經(jīng)知道:要實(shí)踐敏捷開發(fā),,可以從哪些工具開始入手。最后我還有一個(gè)忠告要給我親愛的讀者:不要被工具綁住你的手腳,。每個(gè)項(xiàng)目,、每個(gè)團(tuán)隊(duì)都是獨(dú)一無二的,它們需要自己獨(dú)一無二的方法,,而你需要針對(duì)項(xiàng)目和團(tuán)隊(duì)的情況選擇適當(dāng)?shù)墓ぞ吆瓦m當(dāng)?shù)氖褂梅绞?。這不是一件容易的事,但愿這篇小文能給你提供一個(gè)好的起點(diǎn),。 |
|