《Microsoft.NET企業級應用架構設計(第2版)》——第1章 今天的架構師和架構 1.1軟件架構到底是什麼
本節書摘來自異步社區《Microsoft.NET企業級應用架構設計(第2版)》一書中的第1章,第1.1節,作者: 【意】Dino Esposito(埃斯波西托) , Andrea Saltarello(索爾塔雷羅)著,更多章節內容可以訪問雲棲社區“異步社區”公眾號查看
第1章 今天的架構師和架構
在計算機的最初年代,硬件成本遠遠大於軟件成本。數十年之後,我們發現情況有了根本的變化。整個工業有了顯著的進步,而硬件成本也急劇下降。另一方麵,軟件成本卻大幅上升,這主要是因為開發自定義企業軟件的複雜性提升了。
這種情況催生了一係列的準則,並以此指導工程師設計這類係統。架構這個術語源自建築行業,現已普遍用於描述規劃、設計和實現軟件密集型係統的藝術。當我們兩個還是青少年時,《愛是……》這部漫畫(https://www.loveiscartoon.com)
正值流行。每期漫畫都會為青少年推薦一則愛的名言。其中一期漫畫說過這樣的話:“愛是必需品,不是奢侈品。”是的,這對於軟件架構也同樣適用。
在第1章裏,我們將會試著分享我們對架構的看法,以及確定並實現它的方法。其中,我們將會了解架構師在這個過程裏扮演的角色,以及我們曾經遇到的控製軟件項目運作的基本規律。毫無疑問,我們的經驗僅僅是我們自己的。雖然我們曾在不同規模的有趣項目裏工作過,但是我們的經驗仍然受限於我們的見識以及教訓。盡管如此,我們希望你把這本書看作一個出發點,和你的團隊耐心、詳細地探討你們如何構建可以正常工作的東西。
注意:
你在本書裏看到的一些定義來自於國際標準,其他則反映我們個人的見解、經驗和感受。我們將會講到架構的一些公認的最佳實踐,但會輔以我們自己的經驗作為補充。我們希望這種組合方式可以幫你把枯燥的國際標準和你在現實世界裏看到的東西聯係起來。
1.1 軟件架構到底是什麼
本書的其中一個作者曾經和一個架構工作室有著密切的聯係。有一天,他們在討論的時候突然提出這樣一個問題:架構是什麼?是藝術,還是僅僅為客戶進行構建?
在軟件裏,架構這個術語恰到好處地指代為客戶構建係統。僅此而已,不多也不少。
也就是說,詳細描述為客戶構建係統所涉及的東西是最難的部分。我們經常思索是否真的有定論。這個問題我們問過無數次,每次都得到相同的答案。雖然這條路不好走,但是我們也要嚐試一下。最糟糕的結果是變成一場頭腦風暴,但頭腦風暴並沒什麼壞處。
那麼,讓我們試著理清軟件架構是什麼,至少搞清我們希望它是什麼。
注意:
架構和架構師這兩個術語常常形影不離。架構師是一個角色,我們將在本章稍後討論架構師這個角色的職責。然而,架構師這個術語仍然讓人認為是一種職業。不幸的是,這個術語背後的專業人士並非全能的。這個頭銜通常帶有修飾語,如企業、解決方案、安全等。除非我們特別指明,否則我們所說的專業人士通常是指軟件架構師或者解決方案架構師。
1.1.1 把架構原則應用到軟件中
我們之中的許多人在成為軟件專家的過程中,一開始認為軟件與現實世界的建築有某種程度的關聯,後來又反對這種觀點。起初把這種類比引入軟件行業是為了表達在構建計算機程序之前需要規劃和設計。但是,設計和構建民用建築與設計和構建可用的軟件係統之間存在著本質的差異。
軟件的存在是為了自動化商業流程和人類行為,而民用建築則作為社區的服務而存在。一般地,民用建築服務針對絕大多數人並提供最優的規劃和實現。他們的目的並非為了滿足少數利益相關者。此外,民用建築的成本很高,造起來也很複雜,因此沒人會對已經敲定的項目隨意做出更改。至少,更改也隻是偶然出現。
軟件則不同。
軟件通常隻為小部分人構建,其中一些人自掏腰包,希望得到一些東西改善他們的組織運作。因此,需求會持續地提煉、添加、移除以及重新劃分優先級。使用這種方式構建軟件需要敏捷性,民用建築采用大量前期設計的做法並不適用於此。
簡而言之,今天的建築架構和軟件架構之間的距離已經沒有20年前那麼接近了。但是,許多字典仍在“架構”這個詞語下麵列出與軟件相關的定義。軟件架構被描述為“計算機係統內部組件的組合、整合和交互”。當然,大家都會認可這個定義。但是,我們認為它過於通用和抽象。
因此,它並不管用。
我們認為軟件專家應該就一個更加細化的解釋達成共識,它對那個定義進行細分,並把它們置於相應的上下文中。
1.根據標準定義架構
許多人好像忘記了軟件架構有一個標準定義。更確切地說,自從美國國家標準學會/電器和電子工程師協會(ANSI/IEEE)於2000年9月發布了第1471號標準《軟件密集型係統架構描述的推薦實踐》以來,這個定義就一直存在了。經過這麼多年,這份文檔也變成國際標準化組織/國際電工委員會(ISO/IEC)的第42010號標準。
軟件架構與軟件密集型係統的組織有關,從利益相關者的角度解決問題和完成使命。這就是國際標準論文給軟件架構這個術語的官方定義。
利益相關者指的是關注係統構建的所有個體。這包括係統的構建者(架構師、開發者、測試者),以及買家、最終用戶、分析師、審核員和首席信息官。
關注點指的是利益相關者的興趣所在,包括係統本身以及他們能在係統上施加的影響,不管是開發方麵的、技術方麵的、運維方麵的、組織方麵的、經濟方麵的,還是法律方麵的。
注意:
我們知道很多人在遇到諸如ISO和ANSI等縮略詞時都會感到害怕。我們有時傾向於避開這些引用,因為它們讓人感到沉悶,讓人想到大學時期的大量理論條文。不管怎樣,標準論文有著大量我們認可的信息。在本章裏,我們引用標準通常是為了說明在某些領域(如處理用戶需求)大量工作已經完成得很好,可以重用。
2.軟件密集型係統圖表
圖1-1所示是根據ISO、IEC和IEEE認證的論文描繪的軟件架構官方圖的核心部分。
係統存在於環境之中,而環境則通過驅動一係列開發和運維的決策來影響係統的設計。雖然當前標準把係統看作相互連接的組件的組合,但是架構也產生了一些後續難以更改的地方。簡而言之,通過架構表達軟件開發可以歸結為做出一些關鍵的決定,它們將會影響開發生命周期,最終也會影響產出係統的質量。
3.我們自己對軟件架構的看法
當新人加入我們公司時,不管他們的技能和角色如何,我們都會向他們介紹我們自己對軟件架構的看法。
我們是意大利人,意大利人對咖啡是非常重視的。就意式咖啡而言,並沒有很多不同種類的咖啡。唯一認可的分類就是好的意式咖啡和不太好的意式咖啡。但當我們來到星巴克,我們也和其他人一樣有著我們自己的口味偏好。
我們想把這個咖啡的類比延伸到軟件架構上。
和意式咖啡一樣,我們也把世上的架構分為好的架構和不太好的架構。為了確保這種做法有意義,我們隻探討有助於開發能夠正常工作的係統的架構。我們不在這裏考慮可能導致係統出問題的不良架構,就像我們不喝不好的意式咖啡一樣!在喝到不好的意式咖啡時,意大利人不會抱怨,隻會直接離開,並給予恰當的(也是尊重的)反饋。
正如我們在星巴克會有我們自己的口味偏好,我們在描述架構時也會有我們自己的看法。我們的看法可以通過一個簡單示意圖闡述,我們認為它能表達我們是如何思考和工作的。(見圖1-2。)
1.1.2 確認需求
係統的使命可以通過一組需求來描述。這些需求最終推動係統架構的形成。
抽象一點地說,需求就是係統的特征,它既可以是功能性的,也可以是非功能性的。功能性需求指的是為了實現特定場景係統必須提供的行為。非功能性需求指的是利益相關者明確提出的係統特性。
功能性和非功能性需求的定義是否標準並廣為接受?事實上,用來確定軟件係統質量特征的國際標準自1991年起就已經存在了。
1.ISO/IEC 9126標準概覽
事實上,沒有確認清楚需求是直接導致軟件項目失敗的常見原因之一,通常也是主要原因。ISO/IEC 9126標準定義了一組軟件產品必須滿足的質量特征。這個標準給出6個質量特征族群,並進一步細分為21個子特征。其主要族群包括功能、可靠性、可用性、效率、可維護性以及可移植性。表1-1詳細解釋這些族群以及與之相關的子特征。
子特征分成兩類:外部特征和內部特征。外部特征麵向用戶,是係統的外部視圖。內部特征麵向係統,是係統的內部視圖。外部特征標識功能性需求;內部特征標識非功能性需求。
新的ISO/IEC 25010標準於2011年3月發布,它取代了ISO/IEC 9126。ISO 25010包含8個產品質量特征和31個子特征。
2.功能性需求
功能性需求定義了軟件該有的功能。功能通過輸入、行為和輸出來描述。功能性需求的主要問題在於描述期望行為。不幸的是,這個描述通常沒有足夠清楚、易懂。
在ISO/IEC 9126文檔裏,功能性需求被描述為軟件提供功能的能力,在特定情況下使用軟件時,這些功能可以滿足明示和暗示的需求。軟件架構對應“什麼”;軟件設計對應“如何”。但是,我們相信,我們往往忘記了第3個維度——“何時”。
你可能還記得1996年Ariane 5運載火箭的災難。簡單地說,在Ariane 5運載火箭初次飛行的過程中,起飛後40秒就墜毀了。根據官方報告,火箭自行解體的原因是一個未處理異常——數值轉換溢出引發的連鎖反應。未處理異常不受控製地上拋,向自行解體模塊傳遞了不協調的軌道數字。由於火箭的狀態被“正確地”解讀為不可挽回地迷失於太空,最終,自我解體隻不過是一個正常的決策罷了。諷刺的是,出現未處理異常的模塊不應該執行,因為在起飛階段是沒有必要的。工程師應該知道起飛階段有可能出現不協調的數字,他們沒有捕獲異常,而是簡單地認為沒有必要,因為這個模塊在起飛階段不會工作!
因此,需求的“何時”維度是有影響的。
你的互聯網應用程序在連接性較差的情況下應該如何反應?它應該出錯嗎?還是應該等待並恢複?它應該對用戶友好嗎?它應該使用緩存數據,然後悄悄地切換到離線模式嗎?沒有公認的答案,應該如何反應取決於可靠性和可恢複性的需求如何。作為一名架構師,你有責任找出答案,有時候需要提出更多的問題,做出更多的思考。有了那些答案就能更好地理解係統,繼而減少出錯或者漏掉所需特性的機會。
理想情況下,所有功能性需求都是在開發階段開始之前收集的,一旦進入開發階段就不會更改。但是,更多的情況是,許多功能性需求隻在開發階段才被發現和完全理解。這就需要重新修訂實現了,有時連模塊甚至子係統的架構也需要重新修訂。做不到這點會導致臭名昭著的“大泥球”綜合症,我們會在下一章討論這個問題。
重要:
在我們職業生涯開始那段時間裏,不管與客戶麵談時聽到的是什麼,我們都傾向於將其認為是金科玉律。就像傻乎乎的Dilbert卡通,我們會責怪自己沒有很好地處理需求,不管這些需求如何大量、沒有條理、充滿矛盾或者缺此漏彼(順便說說,前麵提到的Dilbert卡通在這裏可以看到:https://dilbert.com/strip/2001-04-14
)。“客戶永遠是對的”曾經是我們的座右銘,而客戶的需求就像法律一樣。這些年來,我們發現客戶對於任何功能性決定總有最終解釋,但是,我們有責任探求出一組明確的選擇。我們需要成功確認從麵談得到的未經處理的需求,繼而在此基礎上製定出一組選擇。
3.非功能性需求
非功能性需求是指利益相關者明確提出的係統特性。其常見特性包括可伸縮性、安全性,或者可訪問性。功能性需求通常與代碼和實現有關,而非功能性需求則通常與係統架構的選擇和相關方麵有關,這些東西往後難以更改。
舉個例子,如何應對極致可伸縮性?
注意:
我們遇到的客戶都聲稱,聯係人應用程序的極致擴展性對於公司的生存和投資者的投資組合穩健而言是必不可少的。不管實際說的是什麼,做的是什麼,我們的陋見是,真正需要極致擴展性的情況是很少的。當然,除非你是在構建下一個Twitter或者Facebook!
擴展性是指隨著連接用戶的增長,產生了更多的工作和流量,但係統仍能提供相同性能的能力。要讓係統更好地擴展,讀寫必須在最短時間內完成。這可能意味著讀取時大量使用緩存,並且使用異步寫入。
類似地,把係統設計成關鍵模塊可以部署到獨立的機器,能夠有效地滿足安全性需求。如果你使用ASP.NET MVC而不是ASP.NET Web Forms來實現網站,那就可以很好地滿足可訪問性需求,因為ASP.NET MVC在渲染HTML方麵提供更多的控製。
一般來說,非功能性需求必須和功能性需求同時確認。後者產生軟件規範;前者則在實現策略上提供幫助,並在技術決策上給予啟發。功能性需求和非功能性需求本身是相關的,並且都會持續發生變化。不過,非功能性需求會迫使我們做出一些艱難決定。
注意:
一些在我們寫書時提供過幫助的朋友在這點上有一些補充。雖然他們同意前麵這節裏的每一句話,但他們想澄清一點:在很多情況下,功能性需求也會影響係統架構的決策和相關方麵,並且往後難以更改。完全正確!
4.收集需求
解釋如何收集和記錄需求的書很多。你可以從中學到,一個好的需求隻針對一個東西,表達上沒有歧義,可以輕易追溯到業務或者利益相關者的需求,不會作廢等。
注意:
如果你想找一本解釋軟件需求理論的書,我們推薦Stephen Withall的《軟件需求模式》(Microsoft Press,2007)。
不過,實際的情況是,業務人員描述的是他們認為自己想要的東西,開發人員構建的是他們認為業務人員想要的東西。不管你在收集需求上投入多少努力,總會出現隱瞞、忽略、忘記,或者被描述的東西隻有一些人清楚,而另一些人並不清楚。這種溝通問題的根源是業務人員和開發人員使用不同的詞匯。
我們堅信架構師和開發者應該和業務人員使用相同的語言。
不管代金券實際上如何編碼才能完整實現,你都必須理解它是什麼。更重要的是,你還需理解業務人員如何看待它。作為一名架構師,你不應該期望業務人員理解你的語言,例如數據庫表、服務和協議之類的東西。相反,是你應該付出必要的努力去理解構成業務領域的實體含義。
重要:
我們在第5章“發現領域架構”介紹的一個關鍵概念促使技術人員和業務人員使用相同語言。這個概念就是統一語言,它是領域驅動設計方法學的支柱之一。
5.我們如何處理需求
處理功能性需求的一個簡單、有效的辦法是根據類別對它們進行分組,就像表1-1所示的那樣。我們通常創建一個Microsoft Office Excel文檔,一個標簽對應一個類別。接著,我們把從麵談中收集到的需求放入對應的類別。
完成之後,我們回顧一遍,碰到空的或者隻有一兩個需求的標簽就停下來。比如說,如果我們在可移植性裏沒找到需求,我們就應該停下來問一下,我們是否了解得足夠多,我們是否提出了足夠多的問題。沒有明確的可移植性需求可能意味著可移植性並非一個需求,也可能意味著我們對它並不了解。
特別地,可移植性與軟件可在不同的環境下使用的能力有關。如果服務後端沒有這種需求,那麼馬上就會引出一個問題,這個後端是否應該隻對Web客戶端可用,或者是否也應該支持iOS和Android客戶端?
1.1.3 什麼是架構,什麼不是
當你考慮創建或定義軟件係統的架構時,你首先試著標識出一組可能的交互組件,它們共同完成被賦予的任務。國際標準並沒提到任何可以把係統細分成多個部分的方法。假設在第一步裏你得到一個概念性的架構以及一些不同角度的視圖。在第二步裏,你需要逐步逼近功能和物理架構。如何做到是很主觀的,即使自頂向下的做法看起來很合理。你把組件劃分得越來越細,然後從這裏開始構建。
分解過程的具體實現取決於項目選用的方法學,你越是敏捷,分解過程越是迭代,表達越是清楚,步驟也越細致和頻繁。分解過程的輸出是一組將會交給開發團隊的規範。此外,規範的內容和格式取決於選用的方法學。你越是敏捷,你留給開發者實現這個架構的自由性和獨立性就越多。
1.定義架構和實現之間的邊界
你在分解係統時標識出來的構成組件代表了將以某種方式實現的功能。組件的設計,它們的接口、它們的職責,以及它們的行為毫無疑問都是架構的組成部分。但是,架構和實現之間是有一道物理邊界把它們分隔開來的。
把這個邊界標識出來很重要,因為在很大程度上它幫助我們定義開發團隊裏麵的角色。尤其是它界定了架構師和開發者之間的邊界。這些年來,我們了解到架構師與開發者之間的區別並沒有蘋果與橙子的那麼大。如果把他們看作同類水果,那麼,假設他們都是蘋果,他們就是紅蘋果與青蘋果,換句話說,隻是不同口味,而不是不同類型的水果。並且,不存在哪種口味更好的說法。
架構和實現之間的邊界會在你觸及黑盒行為時顯現出來。黑盒行為隻是一塊功能,可以輕易替換和重構而不會帶來顯著回歸,並且對架構的其他部分造成很少影響,甚至沒有影響。在黑盒行為之上的東西則可能與架構相關,並且可能需要你做出艱難決定。
那麼,我們如何定義好的架構?答案是:架構裏的所有艱難決策最後都被證實是對的。
2.艱難決定的科學
軟件係統有些方麵和特性,一旦進入開發階段就難以更改(隻是難,而不是不可能)。其他方麵和特性則可以在任何時候毫不費力地更改,也不會對係統產生顯著影響。
Martin Fowler在他的《企業應用架構模式》(Addison-Wesley,2002)裏提到:
如果你發現有些東西比你想象的更易實現,那麼它不再屬於架構範疇了。最終,架構歸結為重要的東西,不管這些東西是什麼。
簡而言之,我們認為架構這個詞包含了所有在項目早期必須認真對待的東西。最終,架構就是找出需要正確處理的關鍵決策,這些決策在項目裏應該盡早處理,但你卻想盡可能押後處理。
3.艱難決定無處不在
當我們提及艱難的架構決定時,我們並不一定是指往後改起來很難或很昂貴的設計決定。難以更改的決定無處不在,從概念層的定義到構造函數的簽名都有。
為了說明這點,我們來看幾個架構問題的例子,如果它們在項目期間出現,你可能會陷入預算限製和期限問題。
第 1 個例子是改變業務邏輯的組織方式。業務邏輯的設計有幾種方案:事務腳本(Transaction Script)、表模塊(Table Module)、領域模型(Domain Model)、對命令和查詢進行分離的領域模型,以及事件溯源(Event Sourcing)等。一旦你做出選擇,比如說,表模塊(這意味著你會把邏輯放入基於數據庫的表構建的倉儲組件,就像多年以來你對DataSet和DataTable做的那樣),把它換成領域模型並非一個下午就能完成的事情。這種改變會對數據層以及應用程序(服務)層造成很大影響,對表現層也可能是這樣。
第2個例子是換一個不同的庫做相同的任務。假設你使用某個庫開發了某個功能。某天,客戶跟你說公司出了一個新的政策,IT部門不得從某個供應商采購產品。現在你要處理一個新的意料之外的非功能性需求,但代價是什麼?在最好的情況下,你可以從授權供應商獲取一個類似的工具,或者你可以自己構建一個類似的工具。此外,你也可以考慮漸進地改變架構,使得這個庫變得不再必要。
注意:
如果你參與過Dino過去兩年舉辦的研討會,你可能已經聽過這段經曆。簡單地說,Dino的公司投標了一個項目,為iOS、Android、Windows Phone和BlackBerry 4個平台構建一個時效性很強的移動應用。這個投標假設了PhoneGap是一個可行方案。不幸的是,使用PhoneGap構建的原型被客戶拒絕了,團隊之前的努力付諸東流了,而剩下的時間不足4周。
團隊麵臨兩個令人不爽的方案:在很短的時間內把事情做4遍,或者發明一些新的東西。團隊設法在一個移動網站上重用PhoneGap的某些標記,然後在4個基礎的、基本上靜態的、隻有圖形的原生應用的窗體裏整合Web視圖。在功能方麵,表現出色,甚至還有時間應對來自Apple的一次不合理的拒絕。然而,在壓力方麵,大家都知道後麵會很痛苦。
第3個艱難決定的例子是改變類的成員的修飾符,這可能不常見。一般而言,當你使用sealed和virtual修飾符時,你承擔的職責並不少。在C#裏,每個類默認都不是密封的,類的每個方法都不是虛方法。在Java裏,方法的情況有所不同,默認都是虛方法。從設計的角度來看,密封類更好。事實上,如果一開始你就知道一個類是密封的,你也據此創建你的代碼,後來發現這個類支持繼承更合理,你可以在不產生破壞性變化以及不損害兼容性的情況下把它改成非密封的。虛方法和類以及類的成員的可見性幾乎也是這樣。反過來的情況就不會那麼順利了。你通常不能在不破壞現有代碼的情況下密封一個類或者把一個虛方法標記成非虛的。
4.環境使決策變難
大約10年前,在一個研討會上,我們聽到一個主講者提到那段時間的一個大實話。他聲稱移動和雲計算對CTO來說是最大的煩事,他們試圖了解可以用兩者來做什麼。
這點記憶引出一種比較痛苦的架構艱難決定。當你知道某個技術或者某個模式可能有用卻沒有任何具體的證明時,你就會麵臨這種決定。你到處尋找案例分析,非常渴望找到它們,或者任何有助於確定采納或排除某些東西的文獻。
就眾所周知的最佳實踐做出決定很容易,因為有大量案例分析。然而,就新的技術(如NoSQL)做出決定相對來說比較困難,因為真實應用程序的案例分析少之又少,有時候甚至帶有偏見。
這就是經典的青少年性思維:那個年齡的每個人都在談論,但沒人真正知道如何做。更過分的是,那個年齡的每個人都認為別人在做,所以每個人都認為自己也應該做。與真正的青少年之間真正的性一樣,唯一的解決之道就是:放手去試!
1.1.4 架構流程
需求經由首席架構師處理之後會交由開發團隊實現。每個人都同意好的架構和好的設計可以加快模塊的實際開發。但構建應用程序實際上應該怎麼做?
原則上,構建軟件是3個群體共同努力的結果:項目管理、開發以及測試/質量控製(QA)。任務的劃分理論上堪稱完美。項目管理團隊負責產品規範、質量標準的定義,以及日程安排。開發團隊確保使用理想的算法以及根據最合適的模式寫代碼。最後,QA團隊對應用程序的行為進行壓力測試,目的是找出它的缺陷,以便通過更新使之變得更加強大。
3個團隊在這個過程裏必須協同工作,雖然某些項目的管理工作需要在開發工作開始之前完成,並且測試也要在某些代碼構建之後才能開始。軟件開發的整個理念是為團隊定義協作規則以及定義他們應該如何互動。軟件開發方法學正是為了解決這個問題。
方法學基本上有兩個主要類型:瀑布和敏捷。使用瀑布模型的項目傾向於按順序經曆一係列階段,以軟件的發布告終。使用敏捷模型的項目傾向於來回迭代任務多次,直到應用程序準備妥當為止,有時候是因為最後期限快到了。選擇方法學在某種程度上決定了架構流程的類型。
1.前期架構
前期架構(upfront architecture)要求一切都在開始之前安排妥當。大量設計工作會在開始寫代碼之前完成。編碼通常被看作把定義明確的想法實際翻譯成編譯指令。
瀑布模型可以追溯到20世紀70年代。在這種模型裏,軟件開發會按順序從一個階段走到下一個階段。基本上,僅當第N步100%完成並且所有人都滿意才會進入第N+1步。圖1-3給出了瀑布模型的示例。
在現實世界裏,階段之間存在某種重合是可以接受的,不過通常是指製訂計劃、做預算以及安排工作日程同時進行。這個方案對於客戶來說很棒,因為它提供了一些明顯的確定性。然而,現實有所不同。項目最終超出預算和最後期限,有時候甚至不能按照預期的需求交付,這些都不是罕見的。這種糟糕的結果在很大程度上是因為要在前期花費大量精力進行設計,這與現代軟件的實際運作並不相容。
軟件設計的根本問題是需求變化很快,當開發結束時,一些需求可能已經不同了。沒有客戶願意為他們明知不能滿足所有需求的軟件付款。此外,客戶根本不喜歡改變和新增的東西帶來的可變成本。
有鑒於此,瀑布模型已是明日黃花,你可以將它的死亡歸咎於軟件開發是一種工程學。
2.漸現架構
今天對架構流程的看法是,任何團隊都應該盡快開始開發,然後獲取早期反饋,在真實代碼上改進軟件。這意味著快速前進,接受甚至擁抱變化,盡早交付一些有價值的東西,以及歡迎反饋。
漸現架構(emerging architecture)是增量構建軟件的流程。初始啟動之後,項目會經過一係列迭代,包括設計、編碼和測試。每次迭代產生這個係統的一個可交付但不完整的版本。每次迭代,團隊會著手處理設計更改,添加新的功能,直到符合整個規範為止。圖1-4所示給出了迭代流程的示意圖。
迭代開發形成敏捷方法學的基礎。“敏捷”這個術語是特意挑選來表明與瀑布模型等重量級方法相反的立場。
在敏捷項目啟動時,可能隻有一些需求完全定義出來,但你知道在項目結束之前會有更多需求呈現出來或者要被澄清。憑借敏捷思維,這不是一個問題。開發過程會在迭代中變得清晰。在迭代開始時,你會和客戶商談現有需求應該實現的部分。在迭代過程裏,你每次隻會關注和實現單個需求。在迭代結束時,你交付一份可工作的軟件。它可能是不完整的,但它可以工作。接著,你進入另一個迭代,關注另一組需求。如果在此期間某些東西發生改變或者被證明是錯的,就會進行重構。這個過程會持續到沒有更多東西要添加為止。迭代的長度以周為單位——通常是兩周。總之,敏捷流程非常敏捷,足以應對變化。而變化在業務裏是常態,不是例外。
敏捷方法學是一個概括性術語。當你提及敏捷方法學時,你並沒有精確指明你實際想說的是哪種方法學。
軟件開發最流行的敏捷方法學是極限編程(XP)。在XP裏,各個階段的執行都是極短的迭代,兩周就會結束。編碼和設計同時進行。
Scrum是另一個流行的敏捷方法學,但它針對的更多是管理項目而不僅僅是開發代碼。Scrum並未指定任何軟件開發模型,但它能與作為開發代碼方法的XP很好地協同工作。若想更多了解Scrum,可以看一下Ken Schwaber的《Agile Project Management with Scrum》(Microsoft Press,2004)。
重要:
敏捷架構有時候會展現出矛盾的一麵,就像在說,如果你使用敏捷,就不用做任何架構分析,你直接開始編碼,關注功能,並且完全忽略建模。老實說,我們的觀點是,雖然敏捷不排除任何這樣的行為,但這種看法通常沒有事實根據。根據我們的經驗,敏捷的做法通常剛好相反,架構和建模問題的處理會貫穿整個開發的生命周期。
3.帶有前期分析的漸現架構
值得一提的是還有第3種方案,介於瀑布和敏捷之間。這個過程包含大量初步的前期分析,然後開始采用經典的敏捷方法學。有些人把它稱作非常有紀律的敏捷方案;也有些人把它稱作Sprint Zero。
然而,更一般地說,我們發現所有軟件開發方法學都有一些共同的特征:若幹需要經曆的階段、若幹將會產生軟件的迭代,以及單個迭代通常的持續時間。所有階段按順序執行,至少有一個迭代以軟件交付告終。不同方法學之間的區別是每個階段進入的順序、需要的迭代數量以及單個迭代的持續時間。接受這個假設之後,采用敏捷方法的步驟會比你原先所想的少很多。
最後更新:2017-06-06 07:36:09