軟件體系架構閱讀筆記(七)

軟件架構構成了一個系統的骨架。它定義了當面對不一樣的功能性和非功能性需求時的系統行爲。一方面,傳統瀑布式方法對項目開發的全部階段提出了硬性約束要求,所以傳統瀑布式方法顯得僵化。另外一方面,敏捷運動讓咱們擁抱改變,即便是處於開發階段後期的改變。儘管咱們正推進本身從僵化的開發模式邁向更靈活的模式,軟件架構因爲其系統骨架的定位,自然地對變化敏感。所以關鍵之處在於,敏捷運動擁抱的軟件架構必須是可持續的——具有可持續概念的軟件架構,支持在項目複雜度不斷增長的同時,系統能以漸進式的、簡單的以及可維護的方法進行擴展。數據庫

在這篇文章裏,我回顧了本身在傳統瀑布式軟件架構和敏捷軟件架構下的工做經歷。描述了二者在如下三個方面表現出來的類似性及差別性:編程

軟件架構扮演的具體角色;緩存

軟件架構的時間跨度;架構

軟件架構的輸出。編程語言

什麼是軟件架構?工具

軟件架構的定義(實際上你也能添加你本身下的定義)成百上千。存在這麼多種定義的緣由在於每一個人都是基於自身情境下定義。我對IEEE給出的定義特別推崇,這個定義描述的基本概念很是形象化。此外,該定義描述出了軟件架構的精髓本質,同時適用於瀑布式和敏捷流程,而不是隻能匹配某一個。在本文的後續部分,我會引述到該定義:測試

一個系統的基本組織結構、基本組成構件和互相之間的關係,以及構件於外部環境間的關係。同時,軟件架構爲後續的設計和架構演化提供了指導性原則。spa

瀑布式軟件架構架構設計

傳統瀑布式開發的特徵在於其由一系列有明確的開始和結束時間的階段構成,每一個階段包含肯定的活動集。全部階段串接在一塊兒,每一個階段嚴重依賴於前一個階段的交付產出。圖1闡述了瀑布式開發過程涉及到的常見階段。設計

 

軟件架構工做一般在軟件需求肯定後開始啓動,認爲在此時,關於系統應作什麼,已經肯定好了。下一步是審查負責肯定軟件架構的人以及當前階段的實際輸出結果。

傳統軟件架構

軟件架構實踐中一般由軟件架構師完成。軟件架構師擁有豐富的技術知識和經驗——每每是由公司中已經達到必定等級的開發人員晉升而來的。軟件架構師負責分析軟件需求,並基於這些需求爲將來系統的演化作某些技術決策。許多公司一般是一個項目對應一個軟件架構師,但在一些更大的公司裏,軟件架構師們可能以團隊的形式共同合做。當項目所在領域很是複雜或者項目的週期很長,好比長達2到3年甚至更久時,一般狀況下就會有軟件架構師團隊。不是全部的公司都有指定的軟件架構師角色——許多公司把這部分職責委託給他們的高級開發人員承擔。在本文的後續部分,我所談的是指由軟件架構師執行的具體活動項,而不是執行活動項的人,除非另有明確說明。

傳統的軟件架構師有4大主要特徵:

關注大格局——軟件架構師應當思考,系統在將來的幾個月(有時間甚至是幾年)會變成什麼樣子。此外,他還應當一併考慮到全部其餘相關的系統(好比第三方系統和數據庫),以及系統間的通信問題。

聽從性導向——軟件架構師應考慮到可能的聽從性問題。可能的有法律規範、許可證、標準或其它,身爲軟件架構師他應確保系統在將來可以知足這些相當重要的標準。

繪製藍圖——軟件架構師的一項重要交付是從不一樣角度描述架構設計的文檔和圖表集。開發團隊利用這些交付件開始進行系統構建。

不太多的實際操做經驗——軟件架構師的工做目標是產出最終文檔以供開發人員使用。儘管軟件架構師一般擁有開發經驗,但他不多參與到開發過程當中去——而是指導開發人員構建已設計好的系統。在某些時候他甚至可能調去參加另外一個項目,留下開發人員本身完成開發。

真實世界之痛

我曾經爲全球最大的啤酒公司的其中之一作一個軟件項目。項目用了2到3年的時間,使用典型的瀑布式方法,在不一樣的階段有對應的負責人——軟件架構師、開發人員、測試人員。我是一個小團隊裏的開發,咱們根據軟件架構師傳達的指示和指導意見,執行系統的開發工做。最初軟件架構師提供在場支持,但過了不久他轉到另外一個項目去了,所以就減少了在這個項目上的工做量。當新的依賴不斷出現,有時候很難照着擬定的軟件架構推動,由於和已有架構設計的規定不相符。儘管嘗試過讓咱們的高級開發人員接管架構設計,但項目仍是逐漸成爲所謂的意大利麪條式代碼(spaghetti code),每一個人都懼怕去改代碼,由於極可能在哪一個地方就出問題了。遺憾的是,項目已經來不及作任何重大的改變了,沒法回到正軌,因此儘管項目最終發佈了,但往後仍然被停掉了。

敏捷運動

傳統的瀑布式架構的性質是一次性活動,活動有明確的起止時間,而敏捷軟件架構是一個持續不斷的過程,也許沒有終點。敏捷軟件架構使咱們能夠對架構設計實施更改,若是須要的話,能夠按期實施。擁抱變化的一大機制是在項目裏運用迭代和增量開發。在Scrum裏,這些迭代被稱之爲sprint,如圖2所示,典型的一個sprint的週期約爲2-4星期。週期窗口如此之小,因此能對提出的任何改變作快速討論。此外,敏捷很是關注團隊的協做,團隊成員之間存在的任何問題應當即解決掉,以防止出現誤解及溝通不順暢的狀況。

 

敏捷運動使得人們能夠擁抱項目中的變化,但它並無告訴你應當以多快的速度響應變化。軟件架構設計做爲系統的骨幹支柱,對變化很是敏感。好比說,在項目中期,你以爲你能更改項目使用的平臺或編程語言嗎?這樣的更改,即使很罕見,也須要經過多輪的迭代才能完成。這種改變甚至能把你從新拉回到項目的啓動階段。當牽扯到軟件架構設計時,有些類型的變化就比較苦楚,須要較多的執行時間。

敏捷軟件架構師

Scrum定義了三類角色:

產品負責人(product owner)——負責提供具體業務領域的信息

scrum master——負責推動團隊的溝通和協做

開發團隊(development team)——負責實現用戶story以及軟件編寫

爲了將傳統軟件架構師角色轉換爲適配敏捷世界,咱們須要先分析下一些可能的變種。構建Scrum團隊的一個方法是讓開發團隊和一個單獨的軟件架構師團隊一塊兒緊密地合做。圖3說明了多Scrum團隊的構建場景。

 

憑這種方法確實能夠完成團隊的構建,但存在兩個問題:

軟件架構師團隊可能會變成需求方,而開發團隊成爲實現方,這正是瀑布式方法下出現的典型狀況。最後呈現的結果是,軟件架構師定義項目的前景,留給開發人員去完成實現。若是開發人員沒有足夠的參與,不被尊重對待,他們的積極性被降低。

上面這樣作的後果,致使一部分開發人員可能也想加入軟件架構師團隊,這樣就可以給其餘開發人員分配工做。Trustpilot提供了一個例子,他們有一個核心團隊和開發團隊,但總的來講卻破壞了工做風氣和彼此的協做,因而他們把核心團隊的全部成員都移到一個開發團隊中去,收到了積極的效果。

另外一種作法是將軟件架構師直接置於開發團隊中。

這種狀況下,敏捷軟件架構師的責任發生了一些變化:

在當前和宏圖願景之間保持平衡——敏捷軟件架構師須要同時思考兩點,當前開發過程當中發生的事情以及將其與整個系統的宏圖願景進行對齊。

實際操做經驗——敏捷軟件架構師同時也是開發人員,參與系統的實現工做。這樣使得敏捷軟件架構師可以得到關於作出的架構決策的第一手反饋信息。

建立原型,明智決策——當須要作出重大的技術決策時,快速建立原型能夠揭示這個決策是否可行以及它會如何影響到現有系統。再者,與全體開發團隊的溝通很是關鍵,團隊合做的效果遠好於獨自一人埋頭苦幹。

關注可持續性——極其重要的一點是,架構設計決策造就可持續的軟件架構,從長期來看,可持續的軟件架構能很好地支撐起項目。我的責任感和情懷是其中不可或缺的一部分。敏捷軟件架構師是開發團隊的一份子,因此如前所述他能獲得本身所作決策的第一手反饋。相比瀑布式方法,軟件架構師的決策傳遞到開發團隊並由開發團隊負責執行,敏捷方法提高了我的責任感。

若是想在不一樣的開發團隊(也多是不一樣的項目)之間共享軟件架構師資源,能夠選擇構建擁有獨立軟件架構師團隊的組織結構。除此以外,若是從事的領域很複雜,須要考慮的視角不少,也能夠採用擁有獨立軟件架構師團隊的組織結構。在這類狀況,必須保證軟件架構師與開發人員的合做緊密,並展示出了對開發人員的支持。敏捷方法關注協做,將軟件架構師從開發人員從分離出來,使得協做變得困難了。結果開發過程變得更貼近於瀑布式模型。我我的更青睞第二種變體,在那軟件架構師處於開發團隊中,所以團隊成員之間的溝通交流更有效。在一個更高的層次上架構師仍能(也應當能)協調一致。

敏捷軟件架構的時間跨度

敏捷軟件架構的一個重要方面是什麼時候開始進行架構設計。不一樣於瀑布式模型對每個階段都作了明肯定義,在敏捷的世界裏,不存在一個全部人都贊成開始的肯定的時間點。一個典型的作法是引入sprint #0,這是一個特殊的sprint,開發環境已經配置好了,一些重要的決策已肯定(好比編程語言、平臺、數據庫等等)。

這種方法有個常見的陷阱,即人們傾向於延長sprint #0,由於總會發現事情「幾乎就快準備好了」。常常聽到「再給一個星期,咱們就能開始進入常規的sprint」這樣的話。不少時候你會發現本身已經在開發系統了,但用戶story還沒見着,由於「提早幫忙完成功能實現真的很酷」。這種狀況你應當預先商定出sprint #0的結束日期,能夠設置在一個常規sprint的持續週期內,或者相似相近的時間。

可能有人會疑惑,萬一到常規sprint應啓動的時候,還沒完成架構設計,要怎麼辦。嗯,其實這也不要緊。事實上有可能永遠不會有準備好的一天。那也不要緊。軟件架構設計是一個持續不斷的過程。你應當常常性地從新看回來,去修正系統的骨幹。在架構設計不能給予支持保證時,你是沒法進行系統開發的。Simon Brown說:

敏捷團隊不必建立敏捷軟件架構。但一個好的架構確能作到敏捷。

控制原則

咱們生活在一個複雜的世界,每個業務領域也都是如此複雜。當構建一個軟件的架構時,真的很容易從一開始就把事情複雜化了,進而讓後續開發更容易出錯。如下兩條原則是作決策時事實上的標準:

保持簡單,愚笨(KISS,Keep It Simple, Stupid)

你不須要它(YAGNI,You Aren’t Gonna Need It)

若是在那一刻咱們真的須要一個具體的功能和作成決策,這兩條原則試圖讓咱們對此作慎重的思考。若是咱們把作決策推遲到一個更晚的時段,就能保持架構的簡單,並所以在一個更長的時間裏方便管理。軟件架構變得複雜的一個一般作法是引入抽象——可能變成一個新的花式層,以一種格式複製數據,而後轉換爲另外一種格式,或者爲了讓代碼具有可測試性,可能建立出許許多多的類、接口、工廠等等。

不過,在運用這兩條原則時還要提防一處陷阱,咱們傾向於把全部事情都延緩處理直到最後一刻。到那個時候,可能已經變得太難實施所需的變動了。爲了避開陷阱,咱們的任務可貴多,由於

咱們不該在最後一刻作出決策,而應在最有責任這麼作的時刻作出決策。

當我準備作出架構上的決策決定時,若是作這個決定的肯定性很高,我一般的作法是先作一些不那麼花時間的小的準備。我也會去諮詢個人同事,咱們一塊兒討論問題。

真實世界之痛

我曾經作過一個輪渡票務在線銷售的項目。這是一個複雜的系統,它須要和4個其它第三方系統進行通信。一開始咱們的首要關注點是基於用戶story完成功能實現。儘管咱們知道咱們須要一個更復雜巧妙的緩存機制,但那時還沒必要要——咱們得先完成當前的用戶story,因而咱們選擇了延緩處理。而後到後面,因爲與其它第三方系統的大量通信,系統變慢了。咱們別無選擇,只能中止用戶story開發,一門心思撲在緩存機制上——但這時事情已經很差辦了。

如何組織文檔

瀑布式方法要求編寫大量的文檔,由於須要用文檔來在不一樣的階段(以及每一個階段的參與者)之間進行信息傳遞。編寫文檔的過程不只耗時間,並且因爲文檔存在對功能的不當描述,還常常形成誤解。更進一步,難以保持文檔的及時更新,由於開發傾向於快速推動,不少時候不會再理會文檔了。正如咱們使用敏捷來迭代地編寫代碼,一樣能夠如此處理文檔。咱們開始只描述系統的重要方面,而後在須要時持續地加入更多新的信息。

哪些內容應寫入文檔

切勿對同一個東西以不一樣的方式作屢次的文檔化處理。舉個例子,有工具能幫助你從代碼中生成圖表——和建立獨立的圖表相比,這樣作方便不少,圖表很容易過期的。除此以外,假如你爲了描述系統的某一方面而建立了可視化工件,就不必再使用文字(除非你想要增長一些不能用視覺方式表達的細節)建立一大堆文本文檔去描述同一件事情。這裏有一點很重要,你和你的團隊應對使用的繪圖符號有一致的理解。

怎樣文檔化可能會想到使用UML來對軟件架構進行文檔化。UML是標準語言,每一個人都能理解,大學裏也教,所以UML必定是團結起組織內每一個人的不二選擇。個人經驗卻顯示,實踐中不多有人使用UML。緣由之一多是UML提供的描述系統的方法很是多,能夠從不一樣的視角進行描述,因此不常用UML的人會感到挫敗。

在敏捷業界,沒有特定的工具用來文檔化軟件架構。可使用塗寫白板、便利貼、文本文檔、wiki等等(見圖5)。實踐中,只使用2到3種不一樣的格式會比較穩妥些,要否則信息可能會變得難以存儲和檢索。好比說,在白板上塗寫一陣後,你可能須要對其進行拍照,這樣就保存下來了圖表的電子版本。若是後面你要再次編輯,這時你得選擇究竟是直接數字編輯照片,仍是從新在白板上畫一遍而後再照一張相。

我用圖表工具來生成系統構件的簡圖。一般用Microsoft Visio或draw.io(已集成在Google Drive中),不過還有大量的其它工具可選,在線和離線的都有。若是開會時在白板上作了繪製,我會在會議結束後用圖表工具重畫一遍如出一轍的圖,以保持我畫的東西的格式統一,彼此不存在大的差別。若是我須要對圖表添加額外的註解,我通常會另行建立文本文檔。

 

總結

軟件架構定義了將來系統的骨架。它不僅是由線點組成的圖畫,而是一系列管理支配着系統開發的完整決策,包括代碼自己。應細緻地考慮每個作出的決策與決定,它們都是一種權衡折衷。敏捷理念要求對變化持開放心態,甚至是來自項目晚期的變化,和傳統的瀑布式模型不一樣,瀑布式模型但願需求比較穩定。不過,系統骨架的變動每每並不容易實施,甚至可能把你拉回到開發階段。所以,不要等到最後一刻才作出該作的決策決定,這點很重要,而應該在最有責任這麼多的時候作出決定,爲此甚至能夠不惜冒點小風險,實現某些在那個時間點不作要求的東西。再者,敏捷軟件架構要求綜合全面地看待宏圖願景和「如今」,構建出一個每一個人都能在上面添磚加瓦的可持續的平臺。

相關文章
相關標籤/搜索