遠在2009年,Martin Fowler與Rebecca Parsons在QCon SF作了一次題爲Agilists and Architects: Allies not Adversaries Presentation的演講。演講主要討論了在敏捷方法中的架構活動。類似的話題,Neal Ford則提出了緊急設計的概念,並發表了名爲Evelutionary Architecture and Emergent Design(演進架構與緊急設計)的系列文章。這是很棒的一個講解演進架構的系列文章,談到了TDD、代碼複用、連貫接口、DSL、重構、慣用法模式、指標等與演進架構和緊急設計有關的內容。安全
Neal Ford對軟件架構的主要觀點基於以下事實:架構
將來是不可預測的;
軟件設計的最終目標是得到完整的源代碼;
系統的複雜度分爲偶發複雜度(accidental complexity)與本質複雜度(essential complexity);併發
因而,咱們應該選擇在最後責任時刻(Last Responsible Moment)去應對系統的複雜度。所謂「最後責任時刻」,即咱們若是未及時採起措施,可能致使複雜度線性增長的時刻,以下圖所示:分佈式
Ford提出的方法就是在開發中善於發現抽象與模式,並藉助測試驅動開發,利用重構去導向設計。同時,咱們還能夠嘗試使用一些考量代碼質量的工具,得到質量指標,經過這些指標去發現問題(這些問題其實就是技術債),而後去及時解決問題。針對較難作出的架構決策,則能夠利用Spike方式快速得出結論,甚至是原型方案。ide
事實上,演進式架構這個話題已是老調重彈。讓咱們再回到2004年,Martin Fowler固然發表了文章Is Design Dead。文中談到了計劃式設計與演進式設計之間的區別。這篇文章算得上是溯本清源。在2007年我本身的書《軟件設計精要與模式》中,也簡單闡述了我對兩者的理解。我給出了一個建築學的隱喻:拙政園與周莊。拙政園是計劃式設計的典範,沒有詳盡的計劃,也許就不會有疏朗典雅的拙政園。周莊卻並不是某人在某一時刻靈感捕捉後的設計成果,而是經歷了數百年的歷史滄桑,漸進地增添與更替各類建築,最後造成如今這般靈秀的水鄉風貌。我在書中寫道:工具
演進的設計,一樣須要遵循架構設計的基本準則,它與計劃的設計惟一的區別是設計的目標。演進的設計提倡知足客戶現有的需求;而計劃的設計則須要考慮將來的功能擴展。演進的設計推崇儘快地實現,追求快速肯定解決方案,快速編碼以及快速實現;而計劃的設計則須要考慮計劃的周密性,架構的完整性並保證開發過程的有條不紊。測試
2010年,我翻譯了George Fairbanks的著做Just Enough Software Architecture。大數據
書中除了計劃式設計和演進式設計以外,還提到了第三種設計:Minimal planned design(最小計劃設計),這算是一種中庸之道的選擇。書中認爲,演進式設計須要與一些敏捷實踐配合,包括重構、測試驅動設計與持續集成。George認爲計劃式設計背後隱藏的思想是在構造開始以前,制訂的計劃能夠設計出很好的細節。他還提到:編碼
當架構爲並行的多個團隊所共享時,計劃式架構設計就具備實踐意義,在子團隊開始工做以前,這種計劃式設計頗爲有效。架構設計
書中還寫道:(對於多團隊開發而言)計劃式架構定義了高層的組件與鏈接器,並與局部的設計相匹配,而子團隊則設計這些組件與鏈接器的內部模型。架構經常會保證總體的不變量與設計決策,例如創建併發策略、鏈接器的標準集、分配高層職責或定義某些局部的質量屬性場景。
最小計劃設計,則介乎於演進式設計與計劃式設計之間。支持這種設計的人認爲:若是徹底採起演進式設計,可能會使得設計走向死衚衕;而計劃式設計又很是難,由於事先對系統並無全面的瞭解,可能致使設計錯誤。在2002年Bill Venners對Martin Fowler的採訪中,Martin Fowler認爲,最合理的分配是20%的計劃式設計,80%的演進式設計。在George的書中,做者認爲須要權衡計劃式與演進式設計。一種作法是在項目初期進行計劃式設計,確保架構可以處理最大的風險。以後,就能夠經過局部的設計來應對需求的變化,或者採用演進式設計,經過推行重構、測試驅動設計與持續集成對架構進行演化。
博客coding the architecture上的一篇文章Just enough architecture,從方法學的角度分析如何得到恰如其分的架構。
文章以及上圖所表達出來的含義是:傳統的瀑布式採起事先設計的作法,能夠認爲是計劃式設計;敏捷方法學傾向於演進式設計;處於其中的RUP則更像是前面提到的最小計劃設計。文中主要仍是關注咱們在架構過程當中如何作到架構的「just enough」。事實上,這一觀點在George Fairbanks的著做Just enough software architecture中被反覆提到,要作到這一點,就須要採用風險驅動模型(Risk-Driven Model)。RDM的架構步驟分爲三步:
其實風險驅動模型的三個步驟很容易理解,關鍵是咱們應該如何識別風險,如何排列優先級,又該如何肯定解決或控制風險的技術,並進行合理地評估,這是風險驅動模型的難點。我認爲RDM帶來的益處在於它給出了一個很是具備實踐意義的驅動原則與方法,它告訴架構師,當咱們在對系統進行架構時,須要從一開始就要重視風險,例如系統的安全性、可伸縮性、安全等諸多與質量屬性有關的技術風險。
總體而言,這三種方式的設計各有優劣,咱們應根據具體的場景,具體的項目,具體的團隊進行鍼對性地分析。應該把握「因地制宜」的原則,認識到不一樣的項目須要不一樣的設計方式。對於不一樣的開發團隊,作出的選擇也會不一樣。例如,若是開發團隊精於重構、測試驅動設計,並能很好地實施持續集成,就能夠考慮採用演進式設計或最小計劃設計。
我我的較傾向於Minimal planned design,至於它在演進式設計與計劃式設計以前的權衡,沒必要徹底照搬Martin Fowler給出的比例。參考DDD的分類,我將計劃式設計的部分規劃到戰略式設計中,此時,我能夠從用例出發,引入Bounded Context來尋找系統的核心領域與子領域。
經過Context Map並結合六邊形架構,能夠幫助咱們識別Context或者說領域之間的通訊方式與集成方式,從而得到整個系統的分佈式架構模型。運用分層架構以及六邊形架構驅動得出的Port與Adapter,能夠幫助咱們得到整個系統的應用邏輯架構。而Context自身,則能夠做爲業務邏輯架構的基礎。
軟件系統的質量屬性算是特殊的一部分,能夠借鑑質量驅動設計或風險驅動設計,來肯定知足質量屬性的架構方案。在這個過程當中,咱們能夠參考經常使用的架構風格與架構模式。例如針對大數據處理、併發處理、資源管理、分佈式架構,都有許多相應的模式與風格可供咱們選擇。架構風格與架構模式的選擇,會直接影響到咱們的系統架構。
當咱們分別有了物理架構、應用邏輯架構與業務邏輯架構以後,計劃式設計的過程就能夠畫一個句號了。因爲咱們有了Context做爲領域邊界,使得咱們可以更好地劃分特性團隊。如DDD所述,團隊之間的關係能夠參考Context Map,例如Partnership、Consumer-Provider等。以後的過程就進入了DDD的戰術設計層面。在這個層次,咱們能夠結合團隊成員的能力來選擇不一樣的設計方法。例如,能夠選擇DDD方法繼續對子領域進行領域建模;也能夠從Application層面,經過用例驅動設計,結合CRC卡和時序圖進一步細化;固然,也能夠經過ATDD與TDD進行測試驅動。
不管選擇何種方式,咱們的設計都應該把握「恰如其分」這個原則,不作沒必要要的「過分工程」。這或者能夠看作敏捷架構的中心原則。