天天看點

《Microsoft.NET企業級應用架構設計(第2版)》——第1章 今天的架構師和架構 1.1軟體架構到底是什麼

本節書摘來自異步社群《microsoft.net企業級應用架構設計(第2版)》一書中的第1章,第1.1節,作者: 【意】dino esposito(埃斯波西托) , andrea saltarello(索爾塔雷羅)著,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視

在計算機的最初年代,硬體成本遠遠大于軟體成本。數十年之後,我們發現情況有了根本的變化。整個工業有了顯著的進步,而硬體成本也急劇下降。另一方面,軟體成本卻大幅上升,這主要是因為開發自定義企業軟體的複雜性提升了。

這種情況催生了一系列的準則,并以此指導工程師設計這類系統。架構這個術語源自建築行業,現已普遍用于描述規劃、設計和實作軟體密集型系統的藝術。當我們兩個還是青少年時,《愛是……》這部漫畫<code>(http://www.loveiscartoon.com)</code>正值流行。每期漫畫都會為青少年推薦一則愛的名言。其中一期漫畫說過這樣的話:“愛是必需品,不是奢侈品。”是的,這對于軟體架構也同樣适用。

在第1章裡,我們将會試着分享我們對架構的看法,以及确定并實作它的方法。其中,我們将會了解架構師在這個過程裡扮演的角色,以及我們曾經遇到的控制軟體項目運作的基本規律。毫無疑問,我們的經驗僅僅是我們自己的。雖然我們曾在不同規模的有趣項目裡工作過,但是我們的經驗仍然受限于我們的見識以及教訓。盡管如此,我們希望你把這本書看作一個出發點,和你的團隊耐心、詳細地探讨你們如何建構可以正常工作的東西。

注意:

你在本書裡看到的一些定義來自于國際标準,其他則反映我們個人的見解、經驗和感受。我們将會講到架構的一些公認的最佳實踐,但會輔以我們自己的經驗作為補充。我們希望這種組合方式可以幫你把枯燥的國際标準和你在現實世界裡看到的東西聯系起來。

本書的其中一個作者曾經和一個架構工作室有着密切的聯系。有一天,他們在讨論的時候突然提出這樣一個問題:架構是什麼?是藝術,還是僅僅為客戶進行建構?

在軟體裡,架構這個術語恰到好處地指代為客戶建構系統。僅此而已,不多也不少。

也就是說,較長的描述為客戶建構系統所涉及的東西是最難的部分。我們經常思索是否真的有定論。這個問題我們問過無數次,每次都得到相同的答案。雖然這條路不好走,但是我們也要嘗試一下。最糟糕的結果是變成一場頭腦風暴,但頭腦風暴并沒什麼壞處。

那麼,讓我們試着理清軟體架構是什麼,至少搞清我們希望它是什麼。

架構和架構師這兩個術語常常形影不離。架構師是一個角色,我們将在本章稍後讨論架構師這個角色的職責。然而,架構師這個術語仍然讓人認為是一種職業。不幸的是,這個術語背後的專業人士并非全能的。這個頭銜通常帶有修飾語,如企業、解決方案、安全等。除非我們特别指明,否則我們所說的專業人士通常是指軟體架構師或者解決方案架構師。

1.1.1 把架構原則應用到軟體中

我們之中的許多人在成為軟體專家的過程中,一開始認為軟體與現實世界的建築有某種程度的關聯,後來又反對這種觀點。起初把這種類比引入軟體行業是為了表達在建構計算機程式之前需要規劃和設計。但是,設計和建構民用建築與設計和建構可用的軟體系統之間存在着本質的差異。

軟體的存在是為了自動化商業流程和人類行為,而民用建築則作為社群的服務而存在。一般地,民用建築服務針對絕大多數人并提供最優的規劃和實作。他們的目的并非為了滿足少數利益相關者。此外,民用建築的成本很高,造起來也很複雜,是以沒人會對已經敲定的項目随意做出更改。至少,更改也隻是偶然出現。

軟體則不同。

軟體通常隻為小部分人建構,其中一些人自掏腰包,希望得到一些東西改善他們的組織運作。是以,需求會持續地提煉、添加、移除以及重新劃分優先級。使用這種方式建構軟體需要靈活性,民用建築采用大量前期設計的做法并不适用于此。

簡而言之,今天的建築架構和軟體架構之間的距離已經沒有20年前那麼接近了。但是,許多字典仍在“架構”這個詞語下面列出與軟體相關的定義。軟體架構被描述為“計算機系統内部元件的組合、整合和互動”。當然,大家都會認可這個定義。但是,我們認為它過于通用和抽象。

是以,它并不管用。

我們認為軟體專家應該就一個更加細化的解釋達成共識,它對那個定義進行細分,并把它們置于相應的上下文中。

1.根據标準定義架構

許多人好像忘記了軟體架構有一個标準定義。更确切地說,自從美國國家标準學會/電器和電子工程師協會(ansi/ieee)于2000年9月釋出了第1471号标準《軟體密集型系統架構描述的推薦實踐》以來,這個定義就一直存在了。經過這麼多年,這份文檔也變成國際标準化組織/國際電工委員會(iso/iec)的第42010号标準。

軟體架構與軟體密集型系統的組織有關,從利益相關者的角度解決問題和完成使命。這就是國際标準論文給軟體架構這個術語的官方定義。

利益相關者指的是關注系統建構的所有個體。這包括系統的建構者(架構師、開發者、測試者),以及買家、最終使用者、分析師、稽核員和首席資訊官。

關注點指的是利益相關者的興趣所在,包括系統本身以及他們能在系統上施加的影響,不管是開發方面的、技術方面的、運維方面的、組織方面的、經濟方面的,還是法律方面的。

我們知道很多人在遇到諸如iso和ansi等縮略詞時都會感到害怕。我們有時傾向于避開這些引用,因為它們讓人感到沉悶,讓人想到大學時期的大量理論條文。不管怎樣,标準論文有着大量我們認可的資訊。在本章裡,我們引用标準通常是為了說明在某些領域(如處理使用者需求)大量工作已經完成得很好,可以重用。

2.軟體密集型系統圖表

圖1-1所示是根據iso、iec和ieee認證的論文描繪的軟體架構官方圖的核心部分。

《Microsoft.NET企業級應用架構設計(第2版)》——第1章 今天的架構師和架構 1.1軟體架構到底是什麼

系統存在于環境之中,而環境則通過驅動一系列開發和運維的決策來影響系統的設計。雖然目前标準把系統看作互相連接配接的元件的組合,但是架構也産生了一些後續難以更改的地方。簡而言之,通過架構表達軟體開發可以歸結為做出一些關鍵的決定,它們将會影響開發生命周期,最終也會影響産出系統的品質。

3.我們自己對軟體架構的看法

當新人加入我們公司時,不管他們的技能和角色如何,我們都會向他們介紹我們自己對軟體架構的看法。

我們是意大利人,意大利人對咖啡是非常重視的。就意式咖啡而言,并沒有很多不同種類的咖啡。唯一認可的分類就是好的意式咖啡和不太好的意式咖啡。但當我們來到星巴克,我們也和其他人一樣有着我們自己的口味偏好。

我們想把這個咖啡的類比延伸到軟體架構上。

和意式咖啡一樣,我們也把世上的架構分為好的架構和不太好的架構。為了確定這種做法有意義,我們隻探讨有助于開發能夠正常工作的系統的架構。我們不在這裡考慮可能導緻系統出問題的不良架構,就像我們不喝不好的意式咖啡一樣!在喝到不好的意式咖啡時,意大利人不會抱怨,隻會直接離開,并給予恰當的(也是尊重的)回報。

正如我們在星巴克會有我們自己的口味偏好,我們在描述架構時也會有我們自己的看法。我們的看法可以通過一個簡單示意圖闡述,我們認為它能表達我們是如何思考和工作的。(見圖1-2。)

《Microsoft.NET企業級應用架構設計(第2版)》——第1章 今天的架構師和架構 1.1軟體架構到底是什麼

1.1.2 确認需求

系統的使命可以通過一組需求來描述。這些需求最終推動系統架構的形成。

抽象一點地說,需求就是系統的特征,它既可以是功能性的,也可以是非功能性的。功能性需求指的是為了實作特定場景系統必須提供的行為。非功能性需求指的是利益相關者明确提出的系統特性。

功能性和非功能性需求的定義是否标準并廣為接受?事實上,用來确定軟體系統品質特征的國際标準自1991年起就已經存在了。

1.iso/iec 9126标準概覽

事實上,沒有确認清楚需求是直接導緻軟體項目失敗的常見原因之一,通常也是主要原因。iso/iec 9126标準定義了一組軟體産品必須滿足的品質特征。這個标準給出6個品質特征族群,并進一步細分為21個子特征。其主要族群包括功能、可靠性、可用性、效率、可維護性以及可移植性。表1-1詳細解釋這些族群以及與之相關的子特征。

《Microsoft.NET企業級應用架構設計(第2版)》——第1章 今天的架構師和架構 1.1軟體架構到底是什麼
《Microsoft.NET企業級應用架構設計(第2版)》——第1章 今天的架構師和架構 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卡通在這裡可以看到:<code>http://dilbert.com/strip/2001-04-14</code>)。“客戶永遠是對的”曾經是我們的座右銘,而客戶的需求就像法律一樣。這些年來,我們發現客戶對于任何功能性決定總有最終解釋,但是,我們有責任探求出一組明确的選擇。我們需要成功确認從面談得到的未經處理的需求,繼而在此基礎上制定出一組選擇。

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給出了瀑布模型的示例。

《Microsoft.NET企業級應用架構設計(第2版)》——第1章 今天的架構師和架構 1.1軟體架構到底是什麼

在現實世界裡,階段之間存在某種重合是可以接受的,不過通常是指制訂計劃、做預算以及安排工作日程同時進行。這個方案對于客戶來說很棒,因為它提供了一些明顯的确定性。然而,現實有所不同。項目最終超出預算和最後期限,有時候甚至不能按照預期的需求傳遞,這些都不是罕見的。這種糟糕的結果在很大程度上是因為要在前期花費大量精力進行設計,這與現代軟體的實際運作并不相容。

軟體設計的根本問題是需求變化很快,當開發結束時,一些需求可能已經不同了。沒有客戶願意為他們明知不能滿足所有需求的軟體付款。此外,客戶根本不喜歡改變和新增的東西帶來的可變成本。

有鑒于此,瀑布模型已是明日黃花,你可以将它的死亡歸咎于軟體開發是一種工程學。

2.漸現架構

今天對架構流程的看法是,任何團隊都應該盡快開始開發,然後擷取早期回報,在真實代碼上改進軟體。這意味着快速前進,接受甚至擁抱變化,盡早傳遞一些有價值的東西,以及歡迎回報。

漸現架構(emerging architecture)是增量建構軟體的流程。初始啟動之後,項目會經過一系列疊代,包括設計、編碼和測試。每次疊代産生這個系統的一個可傳遞但不完整的版本。每次疊代,團隊會着手處理設計更改,添加新的功能,直到符合整個規範為止。圖1-4所示給出了疊代流程的示意圖。

《Microsoft.NET企業級應用架構設計(第2版)》——第1章 今天的架構師和架構 1.1軟體架構到底是什麼

疊代開發形成靈活方法學的基礎。“靈活”這個術語是特意挑選來表明與瀑布模型等重量級方法相反的立場。

在靈活項目啟動時,可能隻有一些需求完全定義出來,但你知道在項目結束之前會有更多需求呈現出來或者要被澄清。憑借靈活思維,這不是一個問題。開發過程會在疊代中變得清晰。在疊代開始時,你會和客戶商談現有需求應該實作的部分。在疊代過程裡,你每次隻會關注和實作單個需求。在疊代結束時,你傳遞一份可工作的軟體。它可能是不完整的,但它可以工作。接着,你進入另一個疊代,關注另一組需求。如果在此期間某些東西發生改變或者被證明是錯的,就會進行重構。這個過程會持續到沒有更多東西要添加為止。疊代的長度以周為機關——通常是兩周。總之,靈活流程非常靈活,足以應對變化。而變化在業務裡是常态,不是例外。

靈活方法學是一個概括性術語。當你提及靈活方法學時,你并沒有精确指明你實際想說的是哪種方法學。

軟體開發最流行的靈活方法學是極限程式設計(xp)。在xp裡,各個階段的執行都是極短的疊代,兩周就會結束。編碼和設計同時進行。

scrum是另一個流行的靈活方法學,但它針對的更多是管理項目而不僅僅是開發代碼。scrum并未指定任何軟體開發模型,但它能與作為開發代碼方法的xp很好地協同工作。若想更多了解scrum,可以看一下ken schwaber的《agile project management with scrum》(microsoft press,2004)。

靈活架構有時候會展現出沖突的一面,就像在說,如果你使用靈活,就不用做任何架構分析,你直接開始編碼,關注功能,并且完全忽略模組化。老實說,我們的觀點是,雖然靈活不排除任何這樣的行為,但這種看法通常沒有事實根據。根據我們的經驗,靈活的做法通常剛好相反,架構和模組化問題的處理會貫穿整個開發的生命周期。

3.帶有前期分析的漸現架構

值得一提的是還有第3種方案,介于瀑布和靈活之間。這個過程包含大量初步的前期分析,然後開始采用經典的靈活方法學。有些人把它稱作非常有紀律的靈活方案;也有些人把它稱作sprint zero。

然而,更一般地說,我們發現所有軟體開發方法學都有一些共同的特征:若幹需要經曆的階段、若幹将會産生軟體的疊代,以及單個疊代通常的持續時間。所有階段按順序執行,至少有一個疊代以軟體傳遞告終。不同方法學之間的差別是每個階段進入的順序、需要的疊代數量以及單個疊代的持續時間。接受這個假設之後,采用靈活方法的步驟會比你原先所想的少很多。