問:敏捷開發(fā)如何融入到現(xiàn)在在推行的CMMI中?
答:首先,我想說一下為什么會在CMM的基礎(chǔ)上提出CMMI。Barry Boehm在其新作《Balancing Agility and Discipline: A Guide for the Perplexed》一書中對此進行了比較深入的闡述。從總體上來說,有兩個主要原因:1、對CMM中那些容易導(dǎo)致官僚的部分進行了大幅度的更改;2、把風(fēng)險驅(qū)動作為一個核心內(nèi)容納入到CMMI的框架之中,這樣在CMMI的框架中就可以比較順暢的制定出一些可以非常敏捷的過程了。但是,CMMI的敏捷性是很難刻畫的,因為作為一個過程改進參考模型,它更加貼近一組需求而不是一組實踐。也就是說,我們只能刻畫那些為滿足這些需求而開發(fā)出的過程。一般來說,CMMI在需求方面的約束少于SW-CMM。如果以更為寬廣的觀點去解釋需求就可以獲取更多的敏捷性。然而,如果在實施時采用了全面保守的做法并且使用了由SW-CMM所提供的重量級成熟度評估方法,那么所得出的CMMI兼容過程將是重型且非常計劃驅(qū)動的。因此,我覺得敏捷本來就可以非常順暢地融入到CMMI的模型中。如果說有問題的話,我覺得更多在于實施者對敏捷的排斥,而非其他。
?
問:敏捷開發(fā)流程是如何應(yīng)對各種可預(yù)知和不可預(yù)知的風(fēng)險? 例如:人員流動和變更,項目周期的變更,客戶代表的變更等風(fēng)險。
答:人員流動和變更、項目周期的變更以及客戶代表的變更等風(fēng)險是任何一個軟件開發(fā)項目都不可避免要面臨的。一個好的過程方法應(yīng)該能夠使得這些風(fēng)險導(dǎo)致的損失最小化。敏捷方法試圖營造一種非常舒適的開發(fā)環(huán)境,這是一種典型的craftsmanship文化。在這種文化中,人們都一自己的技藝為榮,以開發(fā)出高質(zhì)量的軟件為榮,并且不斷追求技藝的提高。在這樣的環(huán)境中,人員流動和變更的頻度被大大地降低。另外,敏捷方法對面對面溝通、結(jié)對編程以及高質(zhì)量代碼和文檔的強調(diào)也使得由于人員變動所導(dǎo)致的風(fēng)險大大降低。
對于項目周期的變更,我想再也沒有比快速、短的迭代更有效的應(yīng)對方法了。正是這些快速的短迭代為我們帶來的大量的反饋信息,使得我們對于項目的狀況具有全面、深入并且是真實的了解。有了這個基礎(chǔ),我們在最小化項目周期變更風(fēng)險方面就處于一個非常有利的位置。而快速的短迭代正是敏捷的重要特征。什么是敏捷呢?敏捷就是:“short cycles that are test-driven and feedback-driven, yielding constant improvements.”對于客戶代表的變更,我不想多說。因為無論是對于敏捷方法還是計劃驅(qū)動方法,客戶代表的變更帶來的風(fēng)險都是一樣的。如果,沒有一個好的客戶代表,那么肯定是一個失敗的項目。
?
問:敏捷開發(fā)流程是否適用于大型、復(fù)雜的應(yīng)用系統(tǒng)?因為對于一些架構(gòu)比較簡單,代碼量小的系統(tǒng),可以通過不斷的代碼重構(gòu)進行改進,但對于一些體系結(jié)構(gòu)比較復(fù)雜的系統(tǒng)在投入運行后,短時間內(nèi),由于客戶業(yè)務(wù)的擴張導(dǎo)致的數(shù)據(jù)容量的增大或者網(wǎng)絡(luò)訪問量的增加, 而導(dǎo)致原有的核心架構(gòu)設(shè)計已經(jīng)不能滿足用戶的需求,而這些重要的架構(gòu)在系統(tǒng)核心服務(wù)中起重要作用而很難進行變更。這種情況,變更這些方面的代價會很高,因此需要早期花費精力預(yù)期此類變更。而且這類軟件的復(fù)雜性和規(guī)模會導(dǎo)致嚴格的代碼重構(gòu)代價過高而且容易出錯。
答:首先我們得在什么是大型、復(fù)雜的應(yīng)用系統(tǒng)這個問題上取得共識。Scrum方法應(yīng)用的最大的一個項目是一個醫(yī)療圖像信息系統(tǒng),共有800人。XP方法應(yīng)用的最大一個項目是一個企業(yè)資源綜合管理系統(tǒng),共有50人。當(dāng)然,在人數(shù)增多時,就必須要采取一些變通的實踐(否則就不敏捷了)。對于架構(gòu)方面的問題,我覺得應(yīng)該這樣看。如果是一個相對成熟的領(lǐng)域,那么可以借鑒很多業(yè)界已有的經(jīng)驗,特別是一些相關(guān)的模式。這一點很重要,否則是要走很多彎路,付出很多代價的。比如:我覺得在并發(fā)、分布式通信領(lǐng)域,一個合格的系統(tǒng)工程師必須應(yīng)該知道并理解《Pattern-Oriented Software Architecture, Volume 2》中的所有模式。但是,這只是為你提供了一個方向,一個防止你犯重大錯誤的方向。這些模式為你代碼的重構(gòu)和系統(tǒng)的演化提供了一個指引。如果不了解這些模式,基本不可能做出一個優(yōu)秀的架構(gòu)。了解了這些模式后,是不是就可以在一開始就把它們堆砌起來以形成一個能夠適應(yīng)未來的架構(gòu)呢?當(dāng)然不行。要想構(gòu)建一個能夠適應(yīng)未來的架構(gòu),有兩種途徑,一種需要天才的系統(tǒng)架構(gòu)師,一種是在領(lǐng)域模式的引導(dǎo)下,通過TDD和Refactoring的方式不斷、逐步地修改。顯然,第2種方法是一種切實可行的方法。
問:敏捷開發(fā)流程是否不支持創(chuàng)建可復(fù)用產(chǎn)品?對于一個工程型,可復(fù)用的產(chǎn)品對于節(jié)約成本和提高效率是極其重要的!
答:關(guān)于可復(fù)用性的問題,一直都是軟件界討論的熱點。一般來說,有機制層面的復(fù)用,比如:一般的函數(shù)庫或者類庫,也有應(yīng)用領(lǐng)域邏輯的復(fù)用,比如:各種領(lǐng)域相關(guān)的應(yīng)用框架。第一種復(fù)用方法相對比較容易,但是帶來的好處也相對較低。而第二種復(fù)用方法能給我們帶來最大的好處,但是非常的困難。也正是因為這一點,在業(yè)界一度有“復(fù)用神話”的說法。無數(shù)實踐表明,要想得到一個相對可用的領(lǐng)域框架,必須要經(jīng)受至少3個同質(zhì)領(lǐng)域?qū)嵺`的錘煉。并且,失敗的數(shù)目要遠遠大于成功的。而試圖在一開始就把可復(fù)用性作為目標(biāo)的項目基本上沒有取得成功的(這樣的框架一般具有這樣的特點:本來一件簡單的任務(wù),但在使用了該框架后卻變得非常復(fù)雜。)。因此,現(xiàn)在業(yè)界比較一致的看法是,首先應(yīng)該針對你開發(fā)的領(lǐng)域搭建一個特定于項目的、簡單的框架。一開始不要考慮復(fù)用性,而關(guān)注于系統(tǒng)的清晰性和簡單性。在另一個同質(zhì)的項目中,通過重構(gòu)、演化的方法在對這個框架進行修正,使之更具通用性,如此循環(huán)往復(fù)。在經(jīng)歷過多個項目后,可能你就得到了一個比較具有可復(fù)用性的框架。也就是說,應(yīng)該關(guān)注于創(chuàng)建那些比較容易演化為可重用框架的東東,這個東東應(yīng)該具有兩個特點:1、針對具體問題;2、非常簡單清晰。敏捷方法非常注重這種框架的形成,但是不會刻意去這樣做,它的思路是在不斷的循環(huán)、迭代中把它演化出來。在這個循環(huán)迭代中,敏捷方法以DRY(Don't Repeat Yourself)原則來逐步建立起更大規(guī)模重用的基礎(chǔ)。
問:敏捷開發(fā)流程的質(zhì)量保證機制是否足夠滿足開發(fā)有嚴格安全性和可靠性要求的軟件?對于在電力,電信系統(tǒng)中一些有嚴格安全性要求的軟件敏捷開發(fā)流程支持的質(zhì)量控制機制似乎并沒有證明來說服使用者軟件是安全的。是否還需其它措施進行補充?
答:首先我要說的是,安全性和可靠性是屬于用戶需求的范疇,而敏捷方法中把客戶滿意放在了非常重要的位置上,單從過程方法的思想基礎(chǔ)方面來說,沒有那種方法能比敏捷方法更關(guān)注客戶的滿意度了。其次,安全性和可靠性不是通過一些條條框框說出來的,那些在系統(tǒng)方案中空洞地羅列一些安全性和可靠性方面的術(shù)語的做法,對于保證系統(tǒng)的可靠性和安全性沒有任何用處。保證安全性和可靠性的唯一方法就是去檢驗,隨著系統(tǒng)的演化,不斷地檢驗。把用戶在安全性和可靠性方面的需求通過測試用例的方式編寫出來,頻繁地去驗證系統(tǒng)是否能夠通過這些測試,如果不通過,就是一次集成失敗。不知大家在保證系統(tǒng)可靠性和安全性方面是如何做的?
問:目前的項目和部門的組織架構(gòu),內(nèi)部客戶和外部客戶離開發(fā)人員都很遠,怎樣能夠達到零距離? 雖然單個客戶和開發(fā)人員在一起工作可以有效對需求變更進行跟蹤,及時響應(yīng)需求變更,但如果系統(tǒng)面對的客戶是不同的,如何避免開發(fā)期間一些需求變更的單一性和獨特性?
答:無論項目采用任何方法,它對于客戶都有同樣的要求,就是這個客戶必須是CRACK(Collaborative、Representative、Authorized、Committed、Knowledgeable)型的客戶。鑒于目前我們所處的各種環(huán)境,完全的CRACK和現(xiàn)場客戶可能不太可能。但是一個能夠合格地擔(dān)當(dāng)其客戶角色,并且能夠比較頻繁的參與到項目開發(fā)中來的人員對于項目的成功來說是必須的。另外,應(yīng)對需求的變化正是敏捷方法的強項,如果這些變化是客戶真正需要的,那么為何要避免呢?此時,我們應(yīng)該利用這些變化取得優(yōu)勢。
問:如何避免開發(fā)人員利用夠用文檔這個借口偷懶少寫文檔?
答:處于敏捷文化中的人以高質(zhì)量地完成任務(wù)為榮,如果寫文檔是高質(zhì)量地完成任務(wù)的一部分,那么他肯定會高質(zhì)量地寫出這份文檔。否則,寫再多言之無物、只滿足格式的文檔又有什么用呢?敏捷實踐都是能夠真正提供開發(fā)人員技能的實踐,敏捷方法強烈反對那些僅僅是為了防止開發(fā)人員“偷懶”而制定的規(guī)程。
?
問:開發(fā)人員面對面的交流過頻繁,導(dǎo)致大會小會不斷,如何把握這個度?
答:面對面交流不是開會。只要覺得需要就去交流。
?
問:簡單設(shè)計的粒度如何把握,如果強調(diào)前期架構(gòu)的簡單設(shè)計,如何應(yīng)對軟件投入運行后,短時間內(nèi),由于客戶業(yè)務(wù)的擴張導(dǎo)致的數(shù)據(jù)容量的增大或者網(wǎng)絡(luò)訪問量的增加,而導(dǎo)致原有的設(shè)計已經(jīng)不能滿足用戶的需求?
答:請參見前面那個關(guān)于架構(gòu)的回答。首先,你要有豐富的經(jīng)驗和知識,這些東西可以為你提供一個架構(gòu)演化的方向。如果沒有這些東西,基本上沒有可能首次就找到正確的方向。有了方向后,下面就是TDD+Refactoring不斷演化。
?
問:簡單設(shè)計如何能保證實施測試驅(qū)動開發(fā)?如果設(shè)計的不夠詳細,如何對接口編寫測試用例和測試代碼?
答:首先,不是簡單設(shè)計保證實施測試驅(qū)動開發(fā),而是測試驅(qū)動開發(fā)可以促使你得到一個簡單的設(shè)計。其次,是先有測試用例,然后才有設(shè)計和接口。
?
問:《敏捷》書中把創(chuàng)建驗收測試作為一種設(shè)計系統(tǒng)架構(gòu)的重要手段,也作為對最終用戶的一種功能演示,但本質(zhì)上還是對系統(tǒng)特性的一種模擬集成測試,并不能完全代表實際系統(tǒng),這種驗收測試與傳統(tǒng)意義上的驗收測試不同,這種驗收測試可靠嗎?
答:這里所指得傳統(tǒng)意義上的驗收測試是什么?是指有測試人員進行的測試嗎?一般在敏捷方法中(特別是XP)所指的驗收測試,都是由QA和客戶代表共同編寫的,如果通過就表明實現(xiàn)了客戶需求。我覺得沒有其他方法能比這個方法更可靠了。
?
問:測試驅(qū)動開發(fā)的例子中,開始也做了簡單的設(shè)計,然后再編寫測試用例,最后形成另外一種設(shè)計。開始時需要設(shè)計嗎?如果需要,應(yīng)該達到什么程度?開始不進行設(shè)計而純粹依靠測試來驅(qū)動設(shè)計可能嗎?我的理解是,測試驅(qū)動開發(fā)更適合于詳細設(shè)計階段,測試驅(qū)動開發(fā)適合于架構(gòu)設(shè)計嗎?文章中的測試驅(qū)動開發(fā)例子中,軟件需求好像來自個人“隨心所欲”的想象,這種測試用例的生成方法是否缺乏系統(tǒng)性和完備性?或者說,測試驅(qū)動開發(fā)的測試用例的產(chǎn)生是否也需要嚴密的設(shè)計呢?
答:什么是設(shè)計?這是一個必須首先達成共識的問題。TDD的核心就是持續(xù)設(shè)計,不斷關(guān)注設(shè)計質(zhì)量,這種關(guān)注是建立在頻繁的、真實的反饋的基礎(chǔ)之上的,而不是一些臆想。達到的程度就是“tuned to today and poised to strike at tomorrow.”通過一些想象畫幾張UML圖,那不是設(shè)計,設(shè)計應(yīng)該是可驗證的,并且要通過反饋持續(xù)修正的。設(shè)計的驗證正是通過測試用例進行的。測試用例可以是客戶需求,這是驗收測試。也可以是開發(fā)團隊內(nèi)部實現(xiàn)上的需求,這是開發(fā)團隊內(nèi)部的測試(一般也成為單元測試)。測試用例應(yīng)該來自客戶,這是勿庸置疑的。測試活動本來就是一項風(fēng)險驅(qū)動活動,在測試投入到達一定水平后,它的效果會迅速降低。對于“系統(tǒng)性”、“完備性”以及“嚴密性”,我不知道具體指得是什么?能不能詳細說明一下,并介紹大家是如何做到需求的“系統(tǒng)性”、“完備性”以及“嚴密性”。
問:敏捷設(shè)計開始設(shè)計的程序也可能是最簡單,不具有靈活性,直到需要變化時,團隊才抓住機會應(yīng)用敏捷設(shè)計原則去改進設(shè)計。這里有幾個前提,團隊?wèi)?yīng)該對不良設(shè)計足夠敏感,才能抓住改進設(shè)計的機會;團隊有足夠的時間去改進設(shè)計。如果這兩個前提不成立,如果進行敏捷設(shè)計?
答:怎樣才具有靈活性呢?把東西做簡單,簡單的東西最具有靈活性!Kent Beck在《eXtreme Programming》一書中對什么是簡單做過明確的定義。用一句話來說,就是:“clean code that works.”如果這些前提不成立的話,那么什么設(shè)計都做不了。很多敏捷實踐的目的就是幫助我們通過學(xué)習(xí)、實踐來培養(yǎng)這種敏感性。
問:測試驅(qū)動開發(fā)過程中如何把握“前進的步伐”,即,每個測試用例的粒度如何把握?粒度大,可以加快開發(fā)速度,但又可能漏掉某些bug;粒度小,又影響開發(fā)進度。如何看待測試驅(qū)動開發(fā)過程中的測試用例?是單元測試嗎?還是粒度很大的集成測試?如果是單元測試,至少也不應(yīng)該是傳統(tǒng)意義上的單元測試,此時的單元測試是屬于黑盒測試還是白盒測試,或者既不是黑盒也不是白盒?如何理解測試驅(qū)動開發(fā)可以改進設(shè)計?有何理論根據(jù)?能夠從黑盒測試的理論闡述這個問題嗎?
答:粒度就是一個獨立的、可以驗證的東西。Kent Beck在其《Test-Driven Development》一書中對使用TDD開發(fā)的節(jié)奏有詳細的描述,我就不再贅述。寫測試覺得不會影響開發(fā)進度,越是在時間壓力大的情況下,越是如此。我想大家都有過這樣的經(jīng)歷吧:“花20分鐘完成了一項功能,然后花2個小時甚至更多的時間去調(diào)試。”在TDD中,測試用例只用兩種,面向客戶的驗收測試用例,和面向開發(fā)團隊內(nèi)部的內(nèi)部測試用例(一般也稱為單元測試)。為什么一定要那么清楚地區(qū)分黑盒和白盒呢?測試驅(qū)動開發(fā)能夠改善設(shè)計的思想基礎(chǔ)在《Test-Driven Development》有詳細闡述。這和黑盒測試沒有任何關(guān)系。TDD更是一種設(shè)計方法,一種有反饋、有驗證的真正的設(shè)計方法。
問:關(guān)于“軟件之美”:對軟件設(shè)計者來說,被簡單、直觀地分割,并具有最小內(nèi)部耦合的內(nèi)部結(jié)構(gòu)就是美的。美的系統(tǒng)是靈活、易于理解的,構(gòu)建、維護它們就是一種快樂。在軟件領(lǐng)域,如何審美?“靈活、易于理解的”這個概念含有很多主觀性,對某一具體的軟件審美,不同的人的評價是不一樣的,大師級別的人當(dāng)然更準(zhǔn)確些,但大師級別的人太少了,那么,有沒有一些客觀的、可以量化的指標(biāo)?使得沒有很多經(jīng)驗的人,也可以以此為指引,改進軟件使之向美的方向發(fā)展?
答:《敏捷軟件開發(fā):原則、實踐和模式》一書中給出了很多原則和實踐方法,可以作為很好的參考。
?
問:極限編程只適用于輕量級團隊和項目,還是也適用于重量級團隊和項目?和CMM等有無矛盾?在推行極限編程哪些可行(如測試驅(qū)動開發(fā)),哪些不可行(如結(jié)對編程)?在重量級團隊和項目中如何運用?
答:極限編程對于小型項目(10~20人)來說肯定沒有問題。對于大型項目來說,照搬XP中的實踐,肯定是會出問題的。所以需要一定程度的根據(jù)具體情況進行修正。關(guān)于和CMM有無矛盾的問題,這方面的討論和文章有很多,基本上是見仁見智。不過,在提高開發(fā)質(zhì)量這個目標(biāo)上是肯定不矛盾的。其實,關(guān)于CMM本身該如何實施方面也存在很多不同意見,不同的評估師給出截然不同的結(jié)論的案例就有很多。其實也沒有必要非得全盤照搬XP不可,我覺得可以在不更改團隊現(xiàn)有運作流程的情況下,先引入小部分實踐,TDD應(yīng)該是首選。
?
問:5個重要的原則“單一職責(zé)原則、開放-封閉原則、Liskov替換原則、依賴倒置原則、接口隔離原則”雖然在此把它們表述為面向?qū)ο笤O(shè)計的原則,但是事實上它們只是軟件工程中一直存在的原則的特例而已。那么,軟件工程中一直存在的普遍性原則是什么?有哪些?在結(jié)構(gòu)化編程還大量應(yīng)用的嵌入式開發(fā)中,如何運用?“為使用而使用”設(shè)計原則會導(dǎo)致不必要的復(fù)雜性,設(shè)計原則是經(jīng)驗的總結(jié),它必然是思考某個問題而得到的解決辦法指導(dǎo),那么,在編程當(dāng)中,時刻要思考的問題有哪些?
答:首先我得說一下,越是具有普遍性得原則,越不具有可實施性,只有針對特定context和force的原則才具有更多的實際意義,這也是模式為何在傳播優(yōu)秀的設(shè)計經(jīng)驗方面得到普遍認可的重要原因。如果非要給出一個普遍原則的話,我覺得Grady Booch曾經(jīng)說過的一句話可以作為參考:“The entire history of sw enginerering is one of rising levels of abstraction.”不論你使用結(jié)構(gòu)化編程還是面向?qū)ο缶幊蹋私舛喾N編程范型肯定會對你的開發(fā)帶來好處。設(shè)計原則和模式只能為你指引方向,最為重要的是要保持(設(shè)計)代碼簡單,時刻思考的問題就是,這段代碼是不是清晰地表達了我的意圖,也就是要intentional programming,要“Keep It DRY, Shy, and Tell the Other Guy.