軟件架構之開發方法
- 第6章:開發方法
- 6.1 軟件生命周期
- 6.2 軟件開發模型
- 6.2.1 瀑布模型
- 6.2.2 演化模型
- 6.2.3 螺旋模型
- 6.2.4 增量模型
- 6.2.5 構件組裝模型
- 6.3 統一過程
- 6.4 敏捷方法
- 6.4.1 極限編程
- 6.4.2 特征驅動開發
- 6.4.3 Scrum
- 6.4.4 水晶方法
- 6.4.5 其他敏捷方法
- 6.5 軟件重用
- 6.5.1 軟件重用
- 6.5.2 構件技術
- 6.6 基于架構的軟件設計
- 6.6.1 ABSD 方法與生命周期
- 6.6.2 基于架構的軟件開發模型
- 6.7 形式化方法
第6章:開發方法
軟件開發方法是軟件開發的方法學。自從“軟件危機”爆發以來,軟件研究人員就在對開發方法進行不斷地研究,以期能夠提高軟件的質量、降低軟件的成本。經過 40 多年的研究,人們提出了很多開發方法,如最初的結構化開發到現在非常流行的面向對象的開發方法等。本章將介紹軟件生命周期、軟件開發模型、軟件重用技術、逆向工程及形式化開發方法。
6.1 軟件生命周期
軟件生命周期也就是軟件生存的周期。同萬物一樣,軟件也有誕生和消亡,軟件生命周期就是指軟件自開始構思與研發到不再使用而消亡的過程。有關軟件生命周期的階段劃分,不同的標準有不同的規定。在 GB8566-88(《軟件工程國家標準——計算機軟件開發規范》)中將軟件生命周期劃分為 8 個階段:可行性研究與計劃、需求分析、概要設計、詳細設計、集成測試、確認測試,使用和維護。
(1)可行性研究與計劃:在決定是否開發軟件之前,首先需要進行可行性研究,來確定開發軟件的必要性,并根據可行性研究的結果初步確定軟件的范圍,風險、開發成本等內容。從而指定出初步的軟件開發計劃。通過可行性研究,如指定該軟件具有研發的必要,則將產生《可行性研究報告》和《軟件開發計劃》,并進入分析的階段。
(2)需求分析:需求分析是軟件開發的重要階段。經過可行性研究后,初步確定了軟件開發的目標和范圍,之后則需要對軟件的需要進行細致的分析,來確定軟件要做成什么樣的。需求分析是軟件開發過程中極其重要的一環,如果需求分析出現了重大偏差,那么軟件開發必然會偏離正確的道路,越走越遠。尤其是需求分析的錯誤如果在軟件開發后期才被發現,修正的代價是非常大的。
(3)設計概要:概要設計確定整個軟件的技術藍圖,負責將需求分析的結果轉化為技術層面的設計方案。在概要設計中,需要確定系統架構、各子系統間的關系、接口規約、數據庫模型、編碼規范等內容。概要設計的結果將作為程序員的工作指南,供程序員了解系統的內部原理,并在其基礎上進行詳細設計和編碼工作。
(4)詳細設計:詳細設計完成編碼前最后的設計,詳細設計在概要設計的基礎上,進行細化,如類設計。詳細設計不是開發過程中必需的階段,在一些規模較小、結構簡單的系統中,詳細設計往往被省略。同樣,在某一次軟件開發中,可能只會對部分關鍵模塊進行詳細設計。
(5)實現:實現過程包括編碼和單元測試。單元測試指的是對剛剛編寫出的一個小的程序單元進行測試,如某一個過程、方法或函數。因為單元測試的對象是小的程序單元,而不是完整的程序,因此往往需要編寫一些測試程序來進行測試。有效的單元測試可以大大提高編碼的質量,降低軟件系統的缺陷率。
(6)集成測試:集成測試又稱為組裝測試。通過單元測試的程序并不意味著沒有缺陷,當程序單元被集成到一起進行交互的時候,往往會出現單元測試中不能發現的問題。同單元測試不同,集成測試必須經過精心的組織,指定集成測試計劃,確定如何將這些程序單元集成到一起,按照什么樣的順序進行測試,使用哪些測試數據等問題。
(7)確認測試:當完成集成測試后,軟件之間的接口方面的錯誤已經排除,這時需要驗證軟件是否同需求一致,是否達到了預期目標。同集成測試一樣,確認測試也需要進行計劃和組織,逐步地驗證軟件系統同需要的一致性。經過確認測試的軟件將投入正常使用,并進入維護期。
(8)使用和維護:即使通過了單元測試、集成測試和確認測試,也不可能發現軟件系統中的全部缺陷;軟件系統的需求也會根據業務的發展變化而變化。因此,在軟件使用過程中,必須不斷地對軟件進行維護,修正軟件中的缺陷,修改軟件中已經不能適應最新情況的功能或者增加新的功能。軟件維護的過程會貫穿整個軟件的使用過程。當使用和維護階段結束后,軟件系統也就自然消亡,軟件系統的生命周期結束。
6.2 軟件開發模型
在計算機剛剛誕生的年代,計算機是一種只有天才才能掌握的工具。人們對軟件的認知僅僅停留在程序的層面上,所謂的軟件開發就是那些能夠掌握計算機的天才們寫的一些只有計算機才能理解的二進制序列。但隨著技術的發展,軟件的復雜度不斷提高,人們進入了大規模軟件開發的時代。這時,人們發現,軟件系統已經變得非常復雜,需要遵循一定的開發方法才能取得成功,于是稱這些模式化的開發方法為開發模型。
6.2.1 瀑布模型
顧名思義,瀑布模型就如同瀑布一樣,從一個特定的階段流向下一個階段,如圖 6-1所示。
1.瀑布模型的核心思想
瀑布模型認為,軟件開發是一個階段化的精確的過程。就像要制造一艘航空母艦,首先需要知道航空母艦的參數(長、寬、高、排水量、航速等)。在這些參數的技術上需要對航空母艦進行設計,設計包括總體設計和詳細設計。只有設計得一清二楚的圖紙才能交付施工,否則造出的零件肯定拼裝不到一起。制造完畢后,要把這些零件一個一個地拼裝起來,拼裝成發動機、船艙等部分,并檢查這些部分是否符合設計標準,這就是集成測試。最后,把各個部分組合在一起,造出一艘巨大的航母。這個過程正如圖 5-1 中的描述,軟件要經過需求分析、總體設計、詳細設計、編碼、調試、集成測試和系統測試階段才能夠被準確地實現。在圖 6-1 中,每一階段都有回到前一階段的反饋線,這指的是,在軟件開發中當在后續階
段發現缺陷的時候,可以把這個缺陷反饋到上一階段進行修正。
從圖 6-1 中可以看出瀑布模型的一個重要特點:軟件開發的階段劃分是明確的,一個階段到下一個階段有明顯的界線。在每個階段結束后,都會有固定的文檔或源程序流入下一階段。在需求分析階段結束后,需要有明確的描述軟件需求的文檔;總體設計結束后,需要有描述軟件總體結構的文檔;詳細設計結束后,需要有可以用來編碼的詳細設計文檔;而編碼結束后,代碼本身被作為文檔流到下一個階段。因此也稱瀑布模型是面向文檔的軟件開發模型。
當軟件需求明確、穩定時,可以采用瀑布模型按部就班地開發軟件,當軟件需求不明確或變動劇烈時,瀑布模型中往往要到測試階段才會暴露出需求的缺陷,造成后期修改代價太大,難以控制開發的風險。
2.瀑布 V 模型
瀑布 V 模型是瀑布模型的一種變體。隨著對瀑布模型的應用,人們發現,缺陷是無法避免的,任何一個階段都會在軟件中引入缺陷,而最后的測試也不能保證軟件完全沒有缺陷,只能爭取在交付前發現更多的缺陷。測試成為軟件開發中非常重要的環節,測試的質量直接影響到軟件的質量。因此,人們對瀑布模型進行了小小的更改,提出了更強調測試的瀑布 V模型,如圖 6-2 所示。
整個瀑布模型在編碼與調試階段轉了個彎,形成了一個對稱的 V 字。瀑布 V 模型同標準瀑布模型一樣,在進行完需求分析后就將進入總體設計階段,但是除總體設計外,需求分析還有一條虛線指向系統測試。這指的是,需求分析的結果將作為系統測試的準則,即需求分析階段也將產生同軟件需求一致的系統測試;同時軟件產品是否符合最初的需求將在系統測試階段得到驗證。以此類推,總體設計對應了集成測試,詳細設計對應了單元測試。瀑布 V 模型不但保持了瀑布模型的階段式文檔驅動的特點,而且更強調了軟件產品的驗證工作。
3.瀑布模型的缺點
雖然是經典的開發模型,但瀑布模型中仍存在一些難以克服的缺陷,即使是在改進的瀑布 V 模型中還是會存在。
首先,在瀑布模型中,需求分析階段是一切活動的基礎,設計、實現和驗證活動都是從需求分析階段的結果導出的。一旦需求分析的結果不完全正確,存在偏差,那么后續的活動只能放大這個偏差,在錯誤的道路上越走越遠。事實上,由于用戶和開發者的立場、經驗、知識域都不相同,不同的人對同一件事物的表述也不同,這就造成需求分析的結果不可能精確、完整地描述整個軟件系統。所以瀑布模型后期的維護工作相當繁重,而這些維護工作大多都是修正在需求分析階段引入的缺陷。這個問題是瀑布模型難以克服的。
其次,瀑布模型難以適應變化。在瀑布模型中精確地定義了每一個階段的活動和活動結果,而每一階段都緊密依賴于上一階段的結果。如果在軟件的后期出現了需求的變化,整個系統又要從頭開始。
再次,使用瀑布模型意味著當所有階段都結束才能最終交付軟件產品,所以在提出需求后需要相當長一段時間的等待才能夠看到最終結果,才能發現軟件產品究竟能不能夠滿足客戶的需求。
最后,文檔驅動型的瀑布模型除了制造出軟件產品外還將產生一大堆的文檔,大部分的文檔對客戶沒有任何意義,但完成這些對客戶沒有意義的文檔卻需要花費大量的人力。所以瀑布模型也是一種重載過程。
6.2.2 演化模型
瀑布模型看起來很好,隨著一個又一個階段的流過,軟件系統就被建立起來了。可是在應用軟件開發的過程中,人們發現很難一次性完全理解用戶的需求、設計出完美的架構,開發出可用的系統,這是由于人的認知本身就是一個過程,這個過程是漸進的、不斷深化的。對于復雜問題,“做兩次”肯定能夠做得更好。那么,對于軟件開發這個復雜而且與人的認知過程緊密相關的事也應該是一個漸進的過程。
演化模型正是基于這個觀點提出的。一般情況下,一個演化模型可以看做若干次瀑布模型的迭代,當完成一個瀑布模型后,重新進入下一個迭代周期,軟件在這樣的迭代過程中得以演化、完善。根據不同的迭代特點,演化模型可以演變為螺旋模型、增量模型和原型法開發。
6.2.3 螺旋模型
螺旋模型將瀑布模型和演化模型結合起來,不僅體現了兩個模型的優點,而且還強調了其他模型均忽略了的風險分析。螺旋模型的每一周期都包括需求定義、風險分析、工程實現和評審 4 個階段,由這 4 個階段進行迭代,軟件開發過程每迭代一次,軟件開發就前進一個層次。采用螺旋模型的軟件過程如圖 6-3 所示。
螺旋模型的基本做法是在“瀑布模型”的每一個開發階段前,引入一個非常嚴格的風險識別、風險分析和風險控制。它把軟件項目分解成一個個小項目,每個小項目都標識一個或多個主要風險,直到所有的主要風險因素都被確定。
螺旋模型強調風險分析,使得開發人員和用戶對每個演化層出現的風險都有所了解,繼而做出應有的反應。因此,螺旋模型特別適用于龐大而復雜、具有高風險的系統,對于這些系統,風險是軟件開發潛在的、不可忽視的不利因素,它可能在不同程度上損害軟件開發過程,影響軟件產品的質量。減小軟件風險的目標是在造成危害之前,及時對風險進行識別、分析,決定采取何種對策,進而消除或減少風險的損害。
與瀑布模型相比,螺旋模型支持用戶需求的動態變化,為用戶參與軟件開發的所有關鍵決策提供了方便,有助于提高目標軟件的適應能力,為項目管理人員及時調整管理決策提供了便利,從而降低了軟件開發風險。
但是,不能說螺旋模型絕對比其他模型優越,事實上,螺旋模型也有其自身的缺點:
(1)采用螺旋模型,需要具有相當豐富的風險評估經驗和專業知識。在風險較大的項目開發中,如果未能及時標識風險,勢必會造成重大損失。
(2)過多的迭代次數會增加開發成本,延遲提交時間。
6.2.4 增量模型
演化模型的另一種形式是增量模型。在系統的技術架構成熟、風險較低的時候,可以采用增量的方式進行系統開發,這樣可以提前進行集成測試和系統測試,縮短初始版本的發布周期,提高用戶對系統的可見度。
對于增量模型,通常有兩種策略。一是增量發布的辦法。即首先做好系統的分析和設計工作,然后將系統劃分為若干不同的版本,每一個版本都是一個完整的系統,后一版本以前一版本為基礎進行開發,擴充前一版本的功能。在這種策略中,第一版本往往是系統的核心功能,可以滿足用戶最基本的需求,隨著增量的發布,系統的功能逐步地豐富、完善起來。用戶在很短的時間內就可以得到系統的初始版本并進行試用。試用中的問題可以很快地反饋到后續開發中,從而降低了系統的風險。在應用增量模型中需要注意:
(1)每一個版本都是一個完整的版本。雖然最初的幾個增量不能完全地實現用戶需求,但這些版本都是完整的、可用的。
(2)版本間的增量要均勻,這一點是很重要的。如果第一個版本花費一個月的時間,而第二個版本需要花費 6 個月的時間,這種不均勻的分配會降低增量發布的意義,需要重新調整。
另一種策略是原型法。同增量發布不同,原型法的每一次迭代都經過一個完整的生命周期。當用戶需求很不明確或技術架構中存在很多不可知因素的時候,可以采用原型法。在初始的原型中,針對一般性的用戶需求進行快速實現,并不考慮算法的合理性或系統的穩定性。這個原型的主要目的是獲得精確的用戶需求,或驗證架構的可用性。一般情況下,會在后面的開發中拋棄這個原型,重新實現完整的系統。
6.2.5 構件組裝模型
隨著軟構件技術的發展,人們開始嘗試利用軟構件進行搭積木式的開發,即構件組裝模型。在構建組裝模型中,當經過需求分析定義出軟件功能后,將對構件的組裝結構進行設計,將系統劃分成一組構件的集合,明確構件之間的關系。在確定了系統構件后,則將獨立完成每一個構件,這時既可以開發軟件構件,也可以重用已有的構件,當然也可以購買或選用第三方的構件。構件是獨立的、自包容的,因此架構的開發也是獨立的,構件之間通過接口相互協作。
構件組裝模型的一般開發過程如圖 6-4 所示。
構件組裝模型的優點如下:
(1)構件的自包容性讓系統的擴展變得更加容易
(2)設計良好的構件更容易被重用,降低軟件開發成本
(3)構件的粒度較整個系統更小,因此安排開發任務更加靈活,可以將開發團隊分成若干組,并行地獨立開發構件。
魚與熊掌不可兼得,構件組裝模型也有明顯的缺點:
(1)對構件的設計需要經驗豐富的架構設計師,設計不良的構件難以實現構件的優點,降低構件組裝模型的重用度。
(2)在考慮軟件的重用度時,往往會對其他方面做出讓步,如性能等。
(3)使用構件組裝應用程序時,要求程序員熟練地掌握構件,增加了研發人員的學習成本。
(4)第三方構件庫的質量會最終影響到軟件的質量,而第三方構件庫的質量往往是開發團隊難以控制的。
6.3 統一過程
統一過程(Unified Process,UP)是由 Rational 公司開發的一種迭代的軟件過程,是一個優秀的軟件開發模型,它提供了完整的開發過程解決方案,可以有效地降低軟件開發過程的風險,經過裁剪的 UP 可以適應各種規模的團隊和系統。
1.UP 的二維模型
UP 是一個很有特色的模型,它本身是一個二維的結構,如圖 6-5 所示。對于 UP 而言,時間主線就是橫軸的階段,隨著時間的流逝,軟件開發活動總要經過初始、細化、構建和交付這 4 個階段方能完成。而縱軸的工作流程則描述了在不同的階段需要進行的主要工作。例如在初始階段,軟件組織需要進行大量的調研,對軟件進行業務建模、需求,同時進行一些設計以驗證建模的合理性,還要進行一些實施甚至測試和部署的工作,用以驗證需求和設計的工作及開發系統原型,當然配置與變更管理、項目管理和環境是在任何階段都是不能缺少的。
從這個模型中可以看出 UP 迭代的特點。任何一個階段的工作都不是絕對的,都是相互交疊配合的。但每一個階段都有其側重點:
在初始階段,開發者剛剛接入系統,此時最重要的工作是界定系統范圍,明確系統目的。在這一階段,業務建模和需求工作成了重頭戲。
在細化階段,開發者需要抽象出軟件的邏輯模型,設計出軟件的架構,在這一階段,分析設計工作是最主要的工程活動。
在構建階段,開發者需要基本完成系統的構建,使之成為一個完整的實體,并進行測試和部署,在這一階段,實施和測試是最主要的活動。
當進入交付階段(該階段也經常被稱為轉移階段),軟件系統需求已經完全成熟或產品化,或進入下一個版本。在這一階段不可避免地要對軟件系統進行重構、修改、測試和部署。
在這 4 個階段中,各有側重點,但也不是像瀑布模型那樣完全不允許其他活動的存在。在初始階段,為了驗證開發者的想法,就需要進行一部分的實施和測試;而即使到了交付階段,需要也可能會發生變化,仍然需要進行部分業務建模、需求和設計的活動。
在每個階段中,系統推進不是一蹴而就的。在圖中將細化階段劃分為第 1 次細化和第 2 次細化,將構建階段也劃分為 3 個小階段。在實際開發中,可以根據實際的需要劃分為更多的小階段來完成。
對于縱軸而言,業務建模、需求、分析設計、實施、測試、部署、配置與變更管理、項目管理、環境稱為 UP 的 9 個核心工作流。可以把這 9 個工作流進行簡單的分類以幫助理解,業務建模、需求、分析設計、實施、測試和部署是工程活動,而配置與變更管理、項
目管理和環境是管理活動。
在這 9 個工作流中,前 8 個可以說是絕大多數人都耳熟能詳的東西,而“環境”工作流則相對難以理解。“環境”工作流很重要,也可以稱之為“環境管理”。俗語說,“巧婦難為無米之炊”,“環境”工作流就是為軟件開發準備“米”的活動。在軟件開發中,需要為各種工作準備相應的工作環境,在工作環境中需要包含必需的工具、活動的指南、活動的流程規范、工作產品的模板、基本的開發設施等。在很多組織中,“環境”工作流沒有得到應有的重視,或者完全被忽視,以為為開發者提供了工作臺和計算機就萬事大吉了,其實這種做法是錯誤的。
每一個開發團體都有自己特定的活動準則和規范,這些準則和規范是團體協作的基礎,萬萬少不得。沒有合理的工具配備,沒有充分的指南、規范和模板,軟件開發的活動肯定是放羊式的管理,管理者除了一些“羊毛”外什么也收獲不到。觀察 UP 模型就可以發現,在每一階段的最開始,“環境”工作流都有一個小小的波峰。在這里面,開發團隊需要為開發環境進行相應的準備并在后續活動中為開發環境提供支持。
2.UP 的生命周期
前面已經提到,UP 模型的時間主線是階段,UP 的生命周期也是與階段一一對應的。在 UP 的生命周期中共有 4 個里程碑:
(1)目標里程碑。目標里程碑對應著先啟階段的結束,當開發者可以明確軟件系統的目標和范圍時即達到了該里程碑。
(2)架構里程碑。架構里程碑是 UP 生命周期中的第二個里程碑,在這個里程碑前,開發者需要確定穩定的系統架構。
(3)能力里程碑。當系統已經足夠的穩定和成熟并完成 Alpha 測試后,認為達到了第3 個里程碑。
(4)發布里程碑。在達到發布里程碑前,需要完成系統的測試、完成系統發布和用戶培訓等工作。
在經過這 4 個里程碑后,即為一個完整的生命周期,開發出一個新的版本。此時可以關閉該產品的開發,也可以迭代進入下一版本。
3.UP 的特點
UP 是一個特點鮮明的開發模型,下面列出 UP 的一些特點:
(1)UP 是一個迭代的二維開發模型,在生命周期的每一階段都可以進行需求、設計等活動。UP 不但給出了迭代的生命周期,還給出了生命周期每一階段的迭代指南。
(2)采用不同迭代方式的 UP 可以演變為演化模型或增量模型。
(3)UP 的迭代特點使得更容易控制軟件開發的風險。
(4)雖然 UP 是一個迭代的開發模型,但 UP 本身并不屬于敏捷方法。相反,一般認為,未經裁減的 UP 是一個重載過程。
(5)在實際應用中可以根據具體問題對 UP 進行裁減,從而使其可以適應各種規模的軟件和開發團隊。
4.架構設計師在 UP 中的活動
架構設計師在 UP 活動中承擔著非常重要的角色。在 UP 中,架構設計師除了需要建立系統架構模型外,還需要:
(1)同需求人員和項目管理人員密切協作。
(2)細化軟件架構。
(3)保持整個架構的概念完整性。
具體地說,架構設計師不但需要設計系統架構,還需要定義設計方法、設計指南、編碼指南、評審設計等工作。因此,有人也稱 UP 是一個以架構為中心的開發模型。
6.4 敏捷方法
2001 年 2 月,在美國的猶他州,17 位“無政府主義者”共同發表了《敏捷軟件開發宣言》,在宣言中指出:
盡早地、持續地向客戶交付有價值的軟件對開發人員來說是最重要的。
擁抱變化,即使在開發的后期。敏捷過程能夠駕馭變化,保持客戶的競爭力。
經常交付可工作的軟件,從幾周到幾個月,時間范圍越小越好。
在整個項目中,業務人員和開發者緊密合作。
圍繞士氣高昂的團隊進行開發,為團隊成員提供適宜的環境,滿足他們的需要,并給予足夠的信任。
在團隊中,最有效率的、也是效果最好的溝通方式是面對面地交流。
可以工作的軟件是進度首要的度量方式。
可持續地開發。投資人、開發團隊和用戶應該保持固定的節奏。
不斷追求優秀的技術和良好的設計有助于提高敏捷性。
要簡單,盡可能減少工作量。減少工作量的藝術是非常重要的。
最好的架構、需求和設計都來自于一個自我組織的團隊。
團隊要定期地總結如何能夠更有效率,然后相應地自我調整。
至此,敏捷軟件聯盟建立起來,敏捷軟件開發方法進入了大發展的時代。這份宣言也就是敏捷方法的燈塔,所有的敏捷方法都在向這個方向努力。目前已形成多種敏捷方法,其中XP 傳播最為廣泛。
6.4.1 極限編程
XP 方法可以說是敏捷聯盟中最鮮艷的一面旗幟,也是相對來說最成熟的一種。XP 方法的雛形最初形成于 1996—1999 年間,Kent Beck、Ward Cunningham、Ron Jeffery 夫婦在開發 C3 項目(Chrysler Comprehensive Compensation)的實踐中總結出了 XP 的基本元素。在此之后,Kent Beck 和他的一些好朋友們一起在實踐中完善提高,終于形成了極限編程方法。
XP 是一種輕量(敏捷)、高效、低風險、柔性、可預測、科學而且充滿樂趣的軟件開發方式。與其他方法論相比,其最大的不同在于:
(1)在更短的周期內,更早地提供具體、持續的反饋信息。
(2)迭代地進行計劃編制,首先在最開始迅速生成一個總體計劃,然后在整個項目開發過程中不斷地發展它。
(3)依賴于自動測試程序來監控開發進度,并及早地捕獲缺陷。
(4)依賴于口頭交流、測試和源程序進行溝通。
(5)倡導持續的、演化式的設計。
(6)依賴于開發團隊內部的緊密協作。
(7)盡可能達到程序員短期利益和項目長期利益的平衡。
XP 由價值觀、原則、實踐和行為四個部分組成,它們彼此相互依賴、關聯,并通過行為貫穿于整個生命周期。
1.四大價值觀
XP 的核心是其總結的溝通、簡單、反饋、勇氣四大價值觀,它們是 XP 的基礎,也是XP 的靈魂。
(1)溝通。通常,程序員給人留下的印象就是“內向、不善言談”,項目中的許多問題就出在這些缺乏溝通的開發人員身上。由于某個程序員做出了一個設計決定,但是卻不能夠及時地通知團隊中的其他成員,結果使得團隊在協作與配合上出現很多麻煩。而在傳統的開發方法中,并不在意這種口頭溝通不暢的問題,而是希望借助于完善的流程和面面俱到的文檔、報表、計劃來替代,但是,這又引入了效率不高的新問題。
XP 方法認為,如果小組成員之間無法做到持續的、無間斷的交流,那么協作就無從談起。從這個角度來看,通過文檔、報表等人工制品進行交流,具有很大的局限性。因此, XP 組合了諸如結對編程這樣的最佳實踐,鼓勵大家進行口頭交流、通過交流解決問題,提高效率。
(2)簡單。XP 方法在工作中秉承“夠用即好”的思路,也就是盡量地簡單化,只要今天夠用就行,不考慮明天會出現的新問題。這一點看上去十分容易,但要真正做到保持簡單的工作其實是很難的,因為在傳統的開發方法中,都要求開發人員對未來做一些預先規劃,以便對今后可能發生的變化預留一些擴展空間。
溝通和簡單之間還有一種相當微妙的互相支持關系。一方面,團隊成員之間溝通得越多,就越容易明白哪些工作需要做,哪些工作不需要做;另一方面,系統越簡單,需要溝通的內容也就越少,溝通也將更加全面。
(3)反饋。是什么原因使得客戶、管理層這么不理解開發團隊?究其癥結,就是開發的過程中缺乏必要的反饋。在很多項目中,當開發團隊經歷過了需求分析階段之后,在一個相當長的時間段中,是沒有任何反饋信息的。整個開發過程對于客戶和管理層而言就像一個黑盒子,進度完全看不到。而且,在項目開發過程中,這樣的現象不僅出現在開發團隊與客戶、管理層之間,還包括在開發團隊內部。因此,開發團隊需要更加注重反饋。反饋對于任何軟件項目的成功都是至關重要的,而在 XP 方法論中則更進一步,通過持續、明確的反饋來暴露軟件狀態的問題。
反饋與溝通有著良好的配合,及時和良好的反饋有助于溝通。而簡單的系統,更有利于測試和反饋。
(4)勇氣。在應用 XP 方法時,每時每刻都在應對變化:由于溝通良好,會有更多需求變更的機會;由于時刻保持系統的簡單,新的變化會帶來一些重新開發的需要;由于反饋及時,會有更多中間打斷思路的新需求。總之,這一切使得開發團隊處于變化之中,因此,這時就需要有勇氣來面對快速開發,面對可能的重新開發。勇氣可以來源于溝通,因為它使得高風險、高回報的試驗成為可能;勇氣可以來源于簡單,因為面對簡單的系統,更容易鼓起勇氣;勇氣可以來源于反饋,因為可以及時獲得每一步前進的狀態(自動測試),會讓人更勇于重構代碼。
在 XP 的四大價值觀之下,隱藏著一種更深刻的東西,那就是尊重。因為這一切都建立在團隊成員之間相互關心、相互理解的基礎之上。
2.十二個最佳實踐
在 XP 中,集成了 12 個最佳實踐,有趣的是,它們沒有一個是創新的概念,大多數概念和編程一樣老。其主要的創新點在于提供一種良好的思路將這些最佳實踐結合在一起,并且確保盡可能徹底地執行,使得它們能夠在最大程度上互相支持。
(1)計劃游戲。計劃游戲的主要思想就是先快速地制定一份概要的計劃,然后,隨著項目細節的不斷清晰,再逐步完善這份計劃。計劃游戲產生的結果是一套用戶故事及后續的一兩次迭代的概要計劃。
(2)小型發布。XP 方法秉承的是“持續集成、小步快走”的哲學思維,也就是說每一次發布的版本應該盡可能地小,當然前提條件是每個版本有足夠的商業價值,值得發布。由于小型發布可以使得集成更頻繁,客戶獲得的中間結果越頻繁,反饋也就越頻繁,客戶就能夠實時地了解項目的進展情況,從而提出更多的意見,以便在下一次迭代中計劃進去,以實現更高的客戶滿意度。
(3)隱喻。相對而言,隱喻比較令人費解。根據詞典中的解釋是:“一種語言的表達手段,它用來暗示字面意義不相似的事物之間的相似之處”。隱喻常用于四個方面:尋求共識、發明共享語匯、創新的武器、描述架構。
如果能夠找到合適的隱喻是十分快樂的,但并不是每一種情況都可
以找到恰當的隱喻,因此,沒有必要去強求,而是順其自然。
(4)簡單設計。強調簡單的價值觀,引出了簡單性假設原則,落到實處就是“簡單設計”實踐。這個實踐看上去似乎很容易理解,但卻又經常被誤解,許多批評者就指責 XP 忽略設計是不正確的。其實,XP 的簡單設計實踐并不是要忽略設計,而是認為設計不應該在編碼之前一次性完成,因為那樣只能建立在“情況不會發生變化”或者“我們可以預見所有的變化”之類的謊言的基礎上。
(5)測試先行。對于有些團隊而言,有時候程序員會以“開發工作太緊張”為理由,繼而忽略測試工作。這樣,就導致了一個惡性循環,越是沒空編寫測試程序,代碼的效率與質量越差,花在找缺陷、解決缺陷的時間也越來越多,實際產能大大降低。由于產能降低,因此時間更緊張,壓力就更大。
(6)重構。重構是一種對代碼進行改進而不影響功能實現的技術,XP 需要開發人員在“聞到代碼的壞味道”時,就有重構代碼的勇氣。重構的目的是降低變化引發的風險、使得代碼優化更加容易。
(7)結對編程。從 20 世紀 60 年代開始,就有類似的實踐在進行,長年以來的研究結果給出的結論是,結對編程的效率反而比單獨編程更高。一開始雖然會犧牲一些速度,但慢慢地,開發速度會逐漸加快。究其原因,主要是結對編程大大降低了溝通的成本,提高了工作的質量。結對編程技術被譽于 XP 保證工作質量、強調人文主義的一個最典型的實踐,應用得當還能夠使開發團隊協作更加順暢、知識交流與共享更加頻繁、團隊穩定性也會更加牢固。
(8)集體代碼所有制。由于 XP 方法鼓勵團隊進行結對編程,而且認為結對編程的組合應該動態地搭配,根據任務的不同、專業技能的不同進行最優組合。因此,每一個人都會遇到不同的代碼,代碼的所有制就不再適合于私有,因為那樣會給修改工作帶來巨大的不便。所謂集體代碼所有制,就是團隊中的每個成員都擁有對代碼進行改進的權利,每個人都擁有全部代碼,也都需要對全部代碼負責。同時,XP 強調代碼是誰破壞的(修改后出現問題),就應該由誰來修復。
集體代碼所有制是 XP 與其他敏捷方法的一個較大不同,也是從
另一個側面體現了 XP 中蘊含的很深厚的編碼情節。
(9)持續集成。在前面談到小型發布、重構、結對編程、集體代碼所有制等最佳實踐的時候,多次提到“持續集成”,可以說持續集成是這些最佳實踐的基本支撐條件。
(10)每周工作 40 小時。這是最讓開發人員開心、管理者反對的一個最佳實踐了,加班、再加班早已成為開發人員的家常便飯,也是管理者最常使用的一種策略。而 XP 方法認為,加班最終會扼殺團隊的積極性,最終導致項目的失敗,這也充分體現了 XP 方法關注人的因素比關注過程的因素更多一些。不過,有一點是需要解釋的,“每周工作 40 小時”中的“40”不是一個絕對數,它所代表的意思是團隊應該保證按照“正常的時間” 進行工作。
(11)現場客戶。為了保證開發出來的結果與客戶的預想接近,XP 方法認為最重要的是需要將客戶請到開發現場。就像計劃游戲中提到過的,在 XP 項目中,應該時刻保證客戶負責業務決策,開發團隊負責技術決策。因此,在項目中有客戶在現場明確用戶故事,并做出相應的業務決策,對于 XP 項目而言有著十分重要的意義。
(12)編碼標準。擁有編碼標準可以避免團隊在一些與開發進度無關的細枝末節問題上發生爭論,而且會給重構、結對編程帶來很大的麻煩。不過,XP 方法的編碼標準的目的不是創建一個事無巨細的規則列表,而是要能夠提供一個確保代碼清晰,便于交流的指導方針。
有句經典名言“1+1>2”最適合表達 XP 的觀點,Kent Beck 認為,XP 方法的最大價值在于,在項目中融會貫通地運用這 12 個最佳實踐,而非單獨使用。當然,可以使用其中的一些實踐,但這并不意味著就應用了 XP 方法。XP 方法真正能夠發揮其效能,就必須完整地運用 12 個實踐。
6.4.2 特征驅動開發
FDD 方法來自于一個大型的新加坡銀行項目。FDD 的創立者 Jeff De Luca 和 Peter Coad 分別是這個項目的項目經理和首席架構設計師。在 Jeff 和 Peter 接手項目時,客戶已經經歷了一次項目的失敗,從用戶到高層都對這個項目持懷疑的態度,項目組士氣低落。
隨后, Jeff 和 Peter 采用了特征驅動、彩色建模等方法,最終獲得了巨大成功。
FDD 是也是一個迭代的開發模型。FDD 的每一步都強調質量,不斷地交付可運行的軟件,并以很小的開發提供精確的項目進度報告和狀態信息。同敏捷方法一樣,FDD 弱化了過程在軟件開發中的地位。雖然 FDD 中也定義了開發的過程,不過一個幾頁紙就能完全描
述的過程深受開發者的喜愛。
1.FDD 角色定義
FDD 認為,有效的軟件開發不可缺少的三個要素是:人、過程和技術。軟件開發不能沒有過程,也不能沒有技術,但軟件開發中最重要的是人。個人的生產率和人的技能將會決定項目的成敗。為了讓項目團隊能夠緊密地工作在一起,FDD 定義了 6 種關鍵的項目角色:
(1)項目經理。項目經理是開發的組織者,但項目經理不是開發的主宰。對于項目團隊來說,項目經理應該是團隊的保護屏障。他將同團隊外界(如高層領導、人事甚至寫字樓的物業管理員)進行溝通,努力為團隊提供一個適宜的開發環境。
(2)首席架構設計師。不難理解,首席架構設計師負責系統架構的設計。
(3)開發經理。開發經理負責團隊日常的開發,解決開發中出現的技術問題與資源沖突。
(4)主程序員。主程序員將帶領一個小組完成特征的詳細設計和構建的工作,一般要求主程序員具有一定的工作經驗,并能夠帶動小組的工作。
(5)程序員。若干個程序員在主程序員的帶領下形成一個開發小組,按照特征開發計劃完成開發。
(6)領域專家。領域專家是對業務領域精通的人,一般由客戶、系統分析員等擔當。
領域專家作為關鍵的項目角色正是敏捷宣言中“業務人員同開發人員緊密合作”的體現。
根據項目規模的大小,有些角色是可以重復的。例如在一個小規模項目中,項目經理自身的能力很強,他就可以同時擔當項目經理、首席架構設計師和開發經理的角色。
2.核心過程
FDD 共有 5 個核心過程,如圖 6-6 所示。
(1)開發整體對象模型。開發整體對象模型也就是業務建模的階段。不過 FDD 強調的是系統地完整地面向對象建模,這種做法有助于把握整個系統,而不僅僅關注系統中的若干個點。在這一階段,領域專家和首席架構設計師相互配合,完成整體對象模型。
(2)構造特征列表。完成系統建模后,需要構造一個完整的特征列表。所謂特征指的是一個小的、對客戶有價值的功能。采用動作、結果和目標來描述特征,特征的粒度最好可以在兩周之內實現。在這一階段中,可以整理出系統的需求。
(3)計劃特征開發。很少看到有哪個軟件在開發過程中明確包含計劃過程,其實任何一個軟件項目都必須有計劃——無論是重載方法還是敏捷方法。在這一階段中,項目經理根據構造出的特征列表、特征間的依賴關系進行計劃,安排開發任務。
(4)特征設計。在這一階段,主程序員將帶領特征小組對特征進行詳細設計,為后面的構建做準備。
(5)特征構建。特征構建和特征設計這兩個階段合并起來可以看做特征的實現階段,這兩個階段反復地迭代,直到完成全部的開發。
3.最佳實踐
組成 FDD 的最佳實踐包括:領域對象建模、根據特征進行開發、類的個體所有、組成特征小組、審查、定期構造、配置管理、結果的可見性。
其中,最有特色的莫過于類的個體所有。幾乎所有的開發模型都是代碼共有,程序員們負責開發系統中的全部代碼,并通過配置管理和變更控制來保持代碼的一致性。在 FDD 中,將類分配給特定的任何小組,分配給 A 成員的代碼將全部由 A 來維護,除 A 外的角色都不能修改它,只能使用它。這樣做當然有它的優點:個人對所分配的類很容易保持概念的完整性;開發類代碼的人肯定是最熟悉這個類的主人;而對這個類的支配感會促使開發人員產生自豪感,從而更出色地完成任務。不過 FDD 也提到了類個體所有的缺陷:項目中的依賴關系增強、當 A 需要 B 修改他自己的類時,必須等待 B 完成修改才能使用;類的個體所有增加了員工離職的損失。面對這些優點和缺陷,顯然 FDD 認為類的個體所有對系統開發更有幫助。
除類的個體所有外,審查也是 FDD 中很具特色的一項實踐。不少人都認為審查是非常嚴格的軟件過程所特有的,因為進行審查不但要花費不少的人力和時間,對審查者本身的素質也有要求。然而在 FDD 中,明確地將審查作為一項最佳實踐提出。審查是一種很有效的發現缺陷的手段,但經常被忽視,國內的軟件組織中很少有嚴格審查制度保證軟件質量。有效的審查可以發現很多潛在的問題,而這些問題往往是無法通過測試發現的,例如建模、需求和設計期的缺陷。這些潛在的缺陷大多要到系統測試甚至發布后才能發現,修正這些缺陷的代價是很大的。
6.4.3 Scrum
Scrum 是一個用于開發和維持復雜產品的框架,是一個增量的、迭代的開發過程。在這個框架中,整個開發過程由若干個短的迭代周期組成,一個短的迭代周期稱為一個 Sprint,每個 Sprint 的建議長度是 2 到 4 周(互聯網產品研發可以使用 1 周的 Sprint)。在 Scrum 中,使用產品 Backlog 來管理產品的需求,產品 Backlog 是一個按照商業價值排序的需求列表,列表條目的體現形式通常為用戶故事。Scrum 團隊總是先開發對客戶具有較高價值的需求。在 Sprint 中,Scrum 團隊從產品 Backlog 中挑選最高優先級的需求進行開發。挑選的需求在 Sprint 計劃會議上經過討論、分析和估算得到相應的任務列表,我們稱它為 Sprint backlog。在每個迭代結束時,Scrum 團隊將遞交潛在可交付的產品增量。 Scrum 起源于軟件開發項目,但它適用于任何復雜的或是創新性的項目。Scrum 的基本流程如圖 6-7 所示。
1.Scrum 的五個活動
Scrum 主要包括:產品待辦事項列表梳理、Sprint 計劃會議、每日 Scrum 會議、Sprint 評審會議、Sprint 回顧會議等五個活動。
(1)產品待辦事項列表梳理
產品待辦事項通常會很大,也很寬泛,而且想法會變來變去、優先級也會變化,所以產品待辦事項列表梳理是一個始終貫穿整個 Scrum 項目的活動。該活動包含但不限于以下的
內容:保持產品待辦事項列表有序、把看起來不再重要的事項移除或者降級、增加或提升涌現出來的或變得更重要的事項、將事項分解成更小的事項、將事項歸并為更大的事項、對事項進行估算。
產品待辦事項列表梳理的一個最大好處是為即將到來的幾個 Sprint 做準備。為此,梳理時會特別關注那些即將被實現的事項。需要考慮不少因素,這包括但不限于以下的內容:
理想情況下,下一個 Sprint 的備選事項都應該提升“商業價值”。開發團隊需要能夠在一個 Sprint 內完成每一個事項。每個人都需要清楚預期產出是什么。 產品開發決定了,有可能需要其他的技能和輸入。因此,產品待辦事項列表梳理最好是所有團隊成員都參與的活動,而不單單是產品負責人。
(2)Sprint 計劃會議
每個 Sprint 都以 Sprint 計劃會議作為開始,這是一個固定時長的會議,在這個會議中,Scrum 團隊共同選擇和理解在即將到來的 Sprint 中要完成的工作。
整個團隊都要參加 Sprint 計劃會議。針對排好序的產品待辦事項列表(Product Backlog),產品負責人和開發團隊成員討論每個事項,并對該事項達成共識,包括根據當前的“完成的定義”,為了完成該事項所需要完成的所有事情。所有的 Scrum 會議都是限定時長的。Sprint 計劃會議推薦時長是 Sprint 中的每周對應兩小時或者更少(例如,一個 Sprint 包含 2 個星期,則 Sprint 計劃會議時長應為 4 個小時或者更少)。因為會議是限制時長的,Sprint 計劃會議的成功十分依賴于產品待辦事項列表的質量。這就是產品待辦事項列表梳理十分重要的原因。
在 Scrum 中,Sprint 計劃會議有兩部分:
決定在 Sprint 中需要完成哪些工作
決定這些工作如何完成
第一部分:需要完成哪些工作?
在會議的第一部分,產品負責人向開發團隊介紹排好序的產品待辦事項,整個 Scrum 團隊共同理解這些工作。
Sprint 中需要完成的產品待辦事項數目完全由開發團隊決定。為了決定做多少,開發團隊需要考慮當前產品增量的狀態,團隊過去的工作情況,團隊當前的生產能力,以及排好序的產品待辦事項列表。做多少工作只能由開發團隊決定。產品負責人或任何其他人,都不能給開發團隊強加更多的工作量。
通常 Sprint 都有個目標,稱作 Sprint 目標。這將十分有效地幫助大家更加專注于需要完成的工作的本質,而不必花太多精力去關注那些對于我們需要完成的工作并不重要的小細節。
第二部分:如何完成工作?
在會議的第二部分里,開發團隊需要根據當前的“完成的定義”一起決定如何實現下一個產品增量。他們進行足夠的設計和計劃,從而有信心可以在 Sprint 中完成所有工作。前幾天的工作會被分解成小的單元,每個工作單元不超過一天。之后要完成的工作可以稍大些,以后再對它們進行分解。
決定如何完成工作是開發團隊的職責,決定做什么則是產品負責人的職責。在計劃會議的第二部分,產品負責人可以繼續留下來回答問題,以及澄清一些誤解。
不管怎樣,團隊應該很容易找到產品負責人。
Sprint 計劃會議的產出。Sprint 計劃會議最終需要 Scrum 團隊對 Sprint 需要完成工作的數量和復雜度達成共識,并預期在一個合理的條件范圍內完成它們。開發團隊預測并共同承諾他們要完成的工作量。總而言之:在 Sprint 計劃會議中,開發團隊和產品負責人一起考慮并討論產品待辦事項,確保他們對這些事項的理解,選擇一些他們預測能完成的事項,創建足夠詳細的計劃來確保他們能夠完成這些事項。最終產生的待辦事項列表就是“Sprint 待辦事項列表(Sprint Backlog)”。
(3)每日 Scrum 會議
開發團隊是自組織的。開發團隊通過每日 Scrum 會議來確認他仍然可以實現 Sprint 的目標。這個會議每天在同樣的時間和同樣的地點召開。每一個開發團隊成員需要提供以下三點信息:
從上一個每日 Scrum 到現在,我完成了什么;
從現在到下一個每日 Scrum,我計劃完成什么;
有什么阻礙了我的進展。
每日 Scrum 中可能有簡要的問題澄清和回答,但是不應該有任何話題的討論。通常,許多團隊會在每日 Scrum 之后馬上開會處理他們遇到的任何問題。
每日 Scrum 既不是向管理層匯報,也不是向產品負責人或者 ScrumMaster 匯報。它是一個開發團隊內部的溝通會議,來保證他們對現狀有一致的了解。只有 Scrum 團隊的成員,包括 ScrumMaster 和產品負責人,可以在會議中發言。其他感興趣的人可以來旁聽。在必要時,開發團隊會基于會議中的發現重新組織他們的工作來完成 Sprint 的目標。
每日 Scrum 是 Scrum 的一個關鍵組成部分,它可以帶來透明性,信任和更好的績效。它能幫助快速發現問題,并促進團隊的自組織和自立。所有 Scrum 會議都是限定時長的。每日 Scrum 通常不超過 15 分鐘。
(4)Sprint 評審會議
Sprint 結束時,Scrum 團隊和相關人員一起評審 Sprint 的產出。Sprint 評審會議的推薦時長是 Sprint 中的每一周對應一個小時(例如,一個 Sprint 包含 2 個星期,則 Sprint 評審會議時長為 2 個小時)。
討論圍繞著 Sprint 中完成的產品增量。由于 Sprint 的產出會涉及一些人的“利益”,因此一個明智的做法是邀請他們參加這個會議,這會很有幫助。這個會議是個非正式的會議,幫助大家了解我們目前進展到哪里,并一起討論我們下一步如何推進。每個人都可以在Sprint 評審會議上發表意見。當然,產品負責人會對未來做出最終的決定,并適當地調整產品待辦事項列表 Product Backlog。
團隊會找到他們自己的方式來開 Sprint 評審會議。通常會演示產品增量,整個小組也會經常討論他們在 Sprint 中觀察到了什么、有哪些新的產品想法出現。他們還會討論產品待辦事項列表的狀態、可能的完成日期以及在這些日期前能完成什么。Sprint 評審會議向每個人展示了當前產品增量的概況。因此,通常都會在 Sprint 評審會議中調整產品待辦事項列表。
(5)Sprint 回顧會議
在每個 Sprint 結束后,Scrum 團隊會聚在一起開 Sprint 回顧會議,目的是回顧一下團隊在流程人際關系以及工具方面做得如何。團隊識別出哪些做得好,哪些做得不好,并找出潛在的改進事項,為將來的改進制定計劃。Sprint 回顧會議的推薦時長是 Sprint 中的每一周對應
一個小時(例如,一個 Sprint 包含 2 個星期,則 Sprint 回顧會議時長為 2 個小時)。 Scrum 團隊總是在 Scrum 的框架內,改進他們自己的流程。
2.Scrum 的 5 大價值觀
Scrum 的 5 大價值觀為:
承諾—愿意對目標做出承諾。
專注—把你的心思和能力都用到你承諾的工作上去。
開放—Scrum 把項目中的一切開放給每個人看。
尊重—每個人都有他獨特的背景和經驗。
勇氣—有勇氣做出承諾,履行承諾,接受別人的尊重。
6.4.4 水晶方法
水晶方法(Crystal),是由 Alistair Cockburn 和 Jim Highsmith 建立的敏捷方法系列,其目的是發展一種提倡“機動性的”方法,包含具有共性的核心元素,每個都含有獨特的角色、過程模式、工作產品和實踐。Crystal 家族實際上是一組經過證明、對不同類型項目非常有效的敏捷過程,它的發明使得敏捷團隊可以根據其項目和環境選擇最合適的 Crystal 家族成員(分為 Crystal Clear,Crystal Yellow,Crystal Orange 和 Crystal Red 分別適用于不同的項
目)。水晶方法中,使用頻度較高的是 Crystal Clear——透明水晶方法。透明水晶方法,適合于一個小團隊來進行敏捷開發,人數在 6 人以下為宜。
透明水晶方法有七大體系特征:
(1)經常交付
任何項目,無論大小、敏捷程度,其最重要的一項體系特征是每過幾個月就向用戶交付已測試的運行代碼。如果你使用了此體系特征,你就會發現,“經常交付”的作用還是很讓人吃驚的。項目主辦者根據團隊的工作進展獲得重要反饋。用戶有機會發現他們原來的需求是否是他們真正想要的,也有機會將觀察結果反饋到開發當中。開發人員打破未決問題的死結,從而實現對重點的持續關注。團隊得以調整開發和配置的過程,并通過完成這些工作鼓舞團隊的士氣。
(2)反思改進
在我們的開發中,時常會出現這樣那樣的問題,技術難題、各種心事等,這會在很大的程度上影響項目的進展。而且,如果其他任務對這項任務有依賴的話,那么其他的任務也會被推遲,這就很可能會導致項目的失敗。換句話說,如果,我們能夠經常在迭代會中及時地反思和改進,那么,這種事情應該是不會發生的,或者說發生了,也能夠很快地找到解決方案去應對它。事實上,從慌亂的日常
開發中,抽出一點時間來思考更為行之有效的工作方法就已經足夠了。
(3)滲透式交流
滲透交流就是信息流向團隊成員的背景聽覺,使得成員就像通過滲透一樣獲取相關信息。這種交流通常都是通過團隊成員在同一間工作室內工作而實現的。若其中一名成員提出問題,工作室內的其他成員可以選擇關注或不關注的態度,可以加入到這個問題的討論當中來,也可以繼續忙自己的工作。
(4)個人安全
個人安全指的是當你指出困擾你的問題時,你不用擔心受到報復。個人安全非常重要,有了它,團隊可以發現和改正自身的缺點。沒有它,團隊成員們知而不言,缺點則愈發嚴重以至于損害整個團隊。個人安全是邁向信任的第一步。有了信任,團隊協作才能真正地實施,開發效率也就會直線上升的。
(5)焦點
所謂“焦點”,就是確定首先要做什么,然后安排時間,以平和的心態開展工作。確保團隊成員清楚地了解他們自己最重要的任務是什么,確保他們能夠有充分的時間去完成這些任務。
(6)與專家用戶建立方便的聯系
與專家用戶持續建立方便的聯系能夠給團隊提供:對經常交付進行配置以及測試的地方,關于成品質量的快速反饋,關于設計理念的快速反饋,最新的(用戶)需求。
(7)配有自動測試、配置管理和經常集成功能的技術環境自動測試可以為開發人員在代碼修改后就可以進行自動測試,并且能夠發現存在的一些bug,以至開發人員能夠及時地進行修改,對于他們來說,節省了時間,提高了效率,而且還不用為煩人的測試而苦惱。
配置管理系統允許人們不同步地對工作進行檢查,可撤銷更改,并且可以將某一系統設置保存后進行新系統的發布,當新系統出現問題,即可還原原系統的設置。
經常集成可以使得團隊在一天之內對系統進行多次集成。其實,團隊越頻繁地對系統進行集成,他們就能夠越快地發現錯誤,堆積到一起的錯誤也會越少,并使他們產生更新的靈感。
最好的團隊是將這三大技術結合成“持續測試集成技術”。這樣做他們可以在幾分鐘內發現因集成所產生的錯誤。
6.4.5 其他敏捷方法
除了上面介紹的幾種敏捷方法,以下敏捷方法我們也需要掌握其基本特征。開放式源碼:開放式源碼指的是開放源碼界所用的一種運作方式。
開放式源碼項目有一個特別之處,就是程序開發人員在地域上分布很廣,這使得它和其他敏捷方法不同,因為一般的敏捷方法都強調項目組成員在同一地點工作。開放源碼的一個突出特點就是查錯
排障(debug)的高度并行性,任何人發現了錯誤都可將改正源碼的“補丁”文件發給維護者。然后由維護者將這些“補丁”或是新增的代碼并入源碼庫。ASD 方法:ASD (Adaptive Software Development)方法由 Jim Highsmith 提出,其核心是三個非線性的、重疊的開發階段:猜測、合作與學習。
6.5 軟件重用
軟件重用技術是一種重要的軟件開發方法,雖然至今軟件重用技術還不夠成熟,離理想中的軟件工廠還有很長的路要走,但現有的一些重用技術(例如,中間件、應用服務器等)已經改變了開發過程。
6.5.1 軟件重用
軟件產品與其他的產品不同,是抽象的,一旦產生就可以無限制地復制,因此重復利用軟件產品的意義重大,可以節約大量的人力物力。軟件重用指的是利用已經存在的軟件元素建立新的軟件系統,這其中的軟件元素既可以是軟件產品、源程序,也可以是文檔、設計思想甚至是領域知識。軟件重用可以直接提高軟件的開發效率、降低軟件的開發成本、縮短軟件的開發周期、提高軟件質量。
常見的軟件重用形式包括:
(1)源代碼重用。這是最簡單也是最常見的重用形式,但由于軟件系統的復雜性,很難大規模地重用已有源代碼。
(2)架構重用。架構重用也很常見,隨著軟件架構風格和設計模式的推廣和應用,架構重用已經對軟件開發產生了重大的影響。
(3)應用框架的重用。隨著軟件技術的發展,應用框架的重用變得越來越普遍,很多成熟的軟件公司都建立了自己的開發框架。在開源社區中,世界各地的技術愛好者也在不斷地推出應用了各種新技術的開發框架,例如,應用了 AOP(Aspect Oriented Programming,面向方面編程)技術的 Spring 等。
(4)業務建模的重用。雖然不同的軟件的業務領域各自不同,但人們還是總結出了一些常見領域的建模方法,重用這些領域模型可以降低因領域知識不足而造成的需求風險。
(5)文檔及過程的重用。軟件文檔和軟件過程也是軟件開發中不可或缺的元素,有效地重用這些文檔和過程也有助于提高開發效率和軟件質量、降低開發成本。
(6)軟構件的重用。關于軟構件的重用,請參考 5.5.2 節。
(7)軟件服務的重用。隨著 Web 服務的提出,人們越來越關注服務的重用。SOA(Service-Oriented Architecture,面向服務的架構)提出了面向服務的軟件架構,并定義了相應的標準。但 SOA 還不夠成熟,相信這一領域在未來的幾年中還將取得更大的進展。
6.5.2 構件技術
構件又稱為組件,是一個自包容、可復用的程序集。首先,構件是一個程序集,或者說是一組程序的集合。這個集合可能會以各種方式體現出來,如源程序或二進制的代碼。這個集合整體向外提供統一的訪問接口,構件外部只能通過接口來訪問構件,而不能直接操作構件的內部。
構件的兩個最重要的特性是自包容與可重用。自包容指的是構件的本身是一個功能完整的獨立體,構件內部與外部的功能界限清晰明確,可以獨立配置與使用。而可重用既是構件的特點,也是構件出現的目的。早在 1968 年 NATO 軟件工程會議,Mcllroy 的論文《大量生產的軟件構件》中,就提出了“軟件組裝生產線”的思想。從那以后,使用構件技術實現軟件復用,采用“搭積木”的方式生產軟件,就成為軟件人員的夢想。
構件的開發者和使用者往往不是相同的人或組織,所以必須定義構件的標準才能夠消除其中的障礙。隨著構件技術的發展,目前應用比較廣泛的構件標準有 CORBA、Java Bean/EJB、COM/DCOM。
應用構件技術開發軟件可以使用構件組裝模型,見 5.5.1 中的介紹。
6.6 基于架構的軟件設計
基于架構的軟件設計(Architecture-Based Software Design,ABSD)是一種架構驅動方法。這種方法有 3 個基礎:
(1)功能的分解。在功能分解中,ABSD 方法使用已有的基于模塊的內聚和耦合技術。
(2)通過選擇架構風格來實現質量和業務需求。
(3)軟件模板的使用。軟件模板利用了一些軟件系統的結構。
然而,對于設計方法來說,軟件模板的使用是一個新概念,下面,我們進行簡單的介紹。 軟件模板是一個特殊類型的軟件元素,包括描述所有這種類型的元素在共享服務和底層構造的基礎上如何進行交互。軟件模板還包括屬于這種類型的所有元素的功能,這些功能的例子有:每個元素必須記錄某些重大事件,每個元素必須為運行期間的外部診斷提供測試點等。在軟件產品線系統中,軟件模板顯得格外重要,因為新元素的引入是一個通用的技術,這種技術用來使產品線架構適應一個特定的產品。
ABSD 方法是遞歸的,且迭代的每一個步驟都是清晰定義的。因此,不管設計是否完成,架構總是清晰的,這有助于降低架構設計的隨意性。
6.6.1 ABSD 方法與生命周期
圖 6-8 描述了 ABSD 方法在生命周期中的位置。盡管我們沒有描述一個需求獲取、組織或跟蹤的特定方法,但還是假設一個需求階段至少部分地完成,從需求階段(包括功能需求、質量和業務需求、約束等)獲得了輸出。ABSD 方法的輸出是三個視圖的概念構件的集合,包括能夠產生每個概念構件的假定、軟件模板的集合和那些已經做出的具體實現的決策,我們把具體實現決策當作附加約束來維護。
在 ABSD 方法中,必須記錄所有做出的決策及這些決策的原理,這有利于決策的可跟蹤性和決策評審。
ABSD 方法的輸入由下列部分組成:
(1)抽象功能需求,包括變化的需求和通用的需求;
(2)用例(實際功能需求);
(3)抽象的質量和業務需求;
(4)質量因素(實際質量和業務需求);
(5)架構選項;
(6)約束。
下面,我們描述需求階段的假定輸出,即 ABSD 方法的輸入。
1.抽象功能需求
ABSD 方法假定需求階段的輸出之一是功能需求的抽象描述,包括這些需求的粗略變化的描述。當獲取需求時,考慮所有最終用戶是重要的。
對一個特定系統來說,通常有不同類型的最終用戶。不同的系統管理員(數據庫管理員、系統管理員、網絡管理員等)都可以是最終用戶。維護工程師也可以是系統的最終用戶。總之,一個最終用戶就是當系統運行時使用系統的任何人員。
與抽象功能需求相聯系的是對公共需求和與這些需求相關的粗略變化的描述,在設計階段,理解這些需求之間的依賴關系是至關重要的。
我們必須在某種抽象級別上獲取功能需求,產品的詳細需求往往要等具體產品開發完成后才能知道。當詳細需求明確時,抽象功能的獲取為詳細需求提供了分類。
2.用例
如前所述,用例是一個或多個最終用戶與系統之間的交互的具體表述,在這里,最終用戶既可以是操作人員,也可以是與系統進行交互操作的其他軟件系統。雖然用例很容易找到和創建,甚至可能有成百上千個,但是,因為我們需要分析用例,所以必須限制用例的數量。
在架構設計階段,只有重要的用例才有用。我們必須對所創建的用例進行分組、設置優先級,以便篩選出最重要的用例,剩下的用例可以在設計階段的任何時候創建。
3.抽象的質量和業務需求
我們必須對待構建系統的質量和業務需求進行編號,每個質量屬性都包含一個特定的刺激,以及希望得到的響應。質量需求要盡量具體化。
4.架構選項
對每個質量和業務需求,我們都要列舉能夠滿足該需求的所有可能的架構。例如,如果需求是支持一系列不同的用戶界面,則可能的架構選擇就是把不同的用戶界面分解成不同的構件。又如,如果需求是保持操作系統的獨立性,則可能的架構選擇就是構建虛擬的操作系統層,接受所有的操作系統調用,并解釋之為當前操作系統所能支持。 在這個時候,只需列舉所有可能的選項,而不需要對這些架構選項進行決策,這種列舉取決于設計師的經驗,既可來自某些書籍介紹,也可直接來自設計師本身的實踐。
5.質量場景
正如用例使功能需求具體化一樣,質量場景使質量需求具體化。質量場景是質量需求的特定擴充。與用例一樣,質量場景也很容易找到和創建,可以創建很多個。我們必須對質量場景進行分組、設置優先級,只需驗證最重要的質量場景。
6.約束
約束是一個前置的設計決策,設計過程本身包含決策。某些決策可以直接由業務目標導出而無須考慮對設計的影響。例如,如果一個公司在某個中間件產品上投入了大量資金,那么在產品的選擇上就可以不必考慮其他決策。在需求獲取階段,約束主要來自系統的業務目標。
在某些特殊情況下,約束由遺留系統決定。今天,幾乎沒有軟件系統不參考已有系統的,常見的情況是,新老系統同時并存,或者新系統替代老系統,但是必須盡可能重用老系統的功能。在設計階段,雖然這些遺留系統處于被設計系統的外部,但設計師必須考慮遺留系統的特征。也就是說,在某種程度上,遺留系統影響著當前的設計,因此,理解遺留系統的結構和解決問題的技術都很重要。出于商業目的,可能要求重用遺留系統的構件,這種需求就變成了約束。
6.6.2 基于架構的軟件開發模型
基于架構的軟件開發模型(Architecture-Based Software Design Model,ABSDM)把整個基于架構的軟件過程劃分為架構需求、設計、文檔化、復審、實現、演化等 6 個子過程,如圖 6-9 所示。
1.架構需求
需求是指用戶對目標軟件系統在功能、行為、性能、設計約束等方面的期望。架構需求受技術環境和架構設計師的經驗影響。需求過程主要是獲取用戶需求,標識系統中所要用到的構件。架構需求過程如圖 6-10 所示。如果以前有類似的系統架構的需求,我們可以從需求庫中取出,加以利用和修改,以節省需求獲取的時間,減少重復勞動,提高開發效率。
(1)需求獲取
架構需求一般來自三個方面,分別是系統的質量目標、系統的業務目標和系統開發人員的業務目標。軟件架構需求獲取過程主要是定義開發人員必須實現的軟件功能,使得用戶能完成他們的任務,從而滿足業務上的功能需求。與此同時,還要獲得軟件質量屬性,滿足一些非功能需求。
(2)標識構件
在圖 6-10 中虛框部分屬于標識構件過程,該過程為系統生成初始邏輯結構,包含大致的構件。這一過程又可分為三步來實現。
第一步:生成類圖。生成類圖的 CASE 工具有很多,例如 Rational Rose 就能自動生成類圖。
第二步:對類進行分組。在生成的類圖基礎上,使用一些標準對類進行分組可以大大簡化類圖結構,使之更清晰。一般地,與其他類隔離的類形成一個組,由泛化關聯的類組成一個附加組,由聚合或組合關聯的類也形成一個附加組。
第三步:把類打包成構件。把在第二步得到的類簇打包成構件,這些構件可以分組合并成更大的構件。
(3)需求評審
組織一個由不同代表(如分析人員、客戶、設計人員、測試人員)組成的小組,對架構需求及相關構件進行仔細的審查。審查的主要內容包括所獲取的需求是否真實反映了用戶的要求,類的分組是否合理,構件合并是否合理等。必要時,可以在“需求獲取—標識構件—需求評審”之間進行迭代。
2.架構設計
架構需求用來激發和調整設計決策,不同的視圖被用來表達與質量目標有關的信息。架構設計是一個迭代過程,如果要開發的系統能夠從已有的系統中導出大部分,則可以使用已有系統的設計過程。軟件架構設計過程如圖 6-11 所示。
(1)提出軟件架構模型
在建立架構的初期,選擇一個合適的架構風格是首要的。在這個風格基礎上,開發人員通過架構模型,可以獲得關于架構屬性的理解。此時,雖然這個模型是理想化的(其中的某些部分可能錯誤地表示了應用的特征),但是,該模型為將來的實現和演化過程建立了目標。
(2)把已標識的構件映射到軟件架構中
把在架構需求階段已標識的構件映射到架構中,將產生一個中間結構,這個中間結構只包含那些能明確適合架構模型的構件。
(3)分析構件之間的相互作用
為了把所有已標識的構件集成到架構中,必須認真分析這些構件的相互作用和關系。
(4)產生軟件架構
一旦決定了關鍵的構件之間的關系和相互作用,就可以在第 2 階段得到的中間架構的基礎上進行細化。
(5)設計評審
一旦設計了軟件架構,我們必須邀請獨立于系統開發的外部人員對架構進行評審。
3.架構文檔化
絕大多數的架構都是抽象的,由一些概念上的構件組成。例如,層的概念在任何程序設計語言中都不存在。因此,要讓系統分析師和程序員去實現架構,還必須得把架構進行文檔化。文檔是在系統演化的每一個階段,系統設計與開發人員的通信媒介,是為驗證架構設計和提煉或修改這些設計(必要時)所執行預先分析的基礎。
架構文檔化過程的主要輸出結果是架構需求規格說明和測試架構需求的質量設計說明書這兩個文檔。生成需求模型構件的精確的形式化的描述,作為用戶和開發者之間的一個協約。
軟件架構的文檔要求與軟件開發項目中的其他文檔是類似的。文檔的完整性和質量是軟件架構成功的關鍵因素。文檔要從使用者的角度進行編寫,必須分發給所有與系統有關的開發人員,且必須保證開發者手上的文檔是最新的。
4.架構復審
從圖 5-8 中我們可以看出,架構設計、文檔化和復審是一個迭代過程。從這個方面來說,在一個主版本的軟件架構分析之后,要安排一次由外部人員(用戶代表和領域專家)參加的復審。
復審的目的是標識潛在的風險,以及早發現架構設計中的缺陷和錯誤,包括架構能否滿足需求、質量需求是否在設計中得到體現、層次是否清晰、構件的劃分是否合理、文檔表達是否明確、構件的設計是否滿足功能與性能的要求,等等。
由外部人員進行復審的目的是保證架構的設計能夠公正地進行檢驗,使組織的管理者能夠決定正式實現架構。
5.架構實現
所謂“實現”就是要用實體來顯示出一個軟件架構,即要符合架構所描述的結構性設計決策,分割成規定的構件,按規定方式互相交互。架構的實現過程如圖 6-12 所示。
圖 6-12 中的虛框部分是架構的實現過程。整個實現過程是以復審后的文檔化的架構說明書為基礎的,每個構件必須滿足軟件架構中說明的對其他構件的責任。這些決定即實現的約束是在系統級或項目范圍內做出的,每個構件上工作的實現者是看不見的。
在架構說明書中,已經定義了系統中構件與構件之間的關系。因為在架構層次上,構件接口約束對外唯一地代表了構件,所以可以從構件庫中查找符合接口約束的構件,必要時開發新的滿足要求的構件。
然后,按照設計提供的結構,通過組裝支持工具把這些構件的實現體組裝起來,完成整個軟件系統的連接與合成。
最后一步是測試,包括單個構件的功能性測試和被組裝應用的整體功能和性能測試。
6.架構演化
在構件開發過程中,最終用戶的需求可能還有變動。在軟件開發完畢,正常運行后,由一個單位移植到另一個單位,需求也會發生變化。在這兩種情況下,就必須相應地修改軟件架構,以適應新的軟件需求。架構演化過程如圖 6-13 所示。架構演化是使用系統演化步驟去修改應用,以滿足新的需求。主要包括以下七個步驟:
(1)需求變動歸類首先必須對用戶需求的變化進行歸類,使變化的需求與已有構件對應。對找不到對應構件的變動,也要做好標記,在后續工作中,將創建新的構件,以對應這部分變化的需求。
(2)制訂架構演化計劃在改變原有結構之前,開發組織必須制訂一個周密的架構演化計劃,作為后續演化開發工作的指南。
(3)修改、增加或刪除構件在演化計劃的基礎上,開發人員可根據在第一步得到的需求變動的歸類情況,決定是否修改或刪除存在的構件、增加新構件。最后,對修改和增加的構件進行功能性測試。
(4)更新構件的相互作用隨著構件的增加、刪除和修改,構件之間的控制流必須得到更新。
(5)構件組裝與測試通過組裝支持工具把這些構件的實現體組裝起來,完成整個軟件系統的連接與合成,形成新的架構。然后對組裝后的系統的整體功能和性能進行測試。
(6)技術評審對以上步驟進行確認,進行技術評審。評審組裝后的架構是否反映需求變動,符合用戶需求。如果不符合,則需要在第 2 到第 6 步之間進行迭代。
(7)產生演化后的架構在原來系統上所作的所有修改必須集成到原來的架構中,完成一次演化過程。
6.7 形式化方法
形式化方法是指采用嚴格的數學方法,使用形式化規約語言來精確定義軟件系統。非形式化的開發方法是通過自然語言、圖形或表格描述軟件系統的行為和特性,然后基于這些描述進行設計和開發,而形式化開發則是基于數學的方式描述、開發和驗證系統。形式化方法包括形式化描述和基于形式化描述的形式化驗證兩部分內容。形式化描述就是用形式化語言進行描繪,建立軟件需求和特性,即解決軟件“做什么”的問題。形式化驗證指的是驗證已有的程序是否滿足形式化描述的定義。形式化描述主要可以分為兩類,一類是通過建立計算模型來描述系統的行為特性,另一類則通過定義系統必須滿足的一些屬性來描述系統。形式化描述又稱之為形式化規約,相對于自然語言描述,形式化描述是精確的、可驗證的,避免了模糊性與二義性,消除需求中相互矛盾的地方,避免需求定義人員和開發人員對需求的理解偏差。
形式化描述可以通過計算機技術進行自動處理,進行一致性的檢查和證明,提高需求分析的效率和質量。通過形式化描述,需求分析的質量大大提高,很多自然語言描述無法避免的缺陷在需求分析階段就會被發現,并得到解決,從而降低后期開發和維護的成本,并提升軟件的質量和可靠性。
在一些要求高可靠性的關鍵應用上,采用形式化開發方法可以保證軟件系統的可靠性。如巴黎地鐵 14 號線和 Roissy 機場穿梭車的自動控制系統。這兩個系統中的部分程序使用了形式化方法進行開發,并取得了很好的效果,如表 6-1 所示。
表 6-1 中的 ADA 代碼行數表示運用形式化方法開發的軟件系統規模,這些代碼是形式化方法自動生成的,開發人員并不需要直接修改這些代碼。
這兩個案例都沒有進行單元測試,而在非形式化開發中,這類關鍵
應用系統的軟件的單元測試和集成測試都是非常重要的工作,通常要付出高昂的代價。形式化開發的優點可見一般。