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