2019年8月,國內出版了[美] 尼爾 · 福特 / [美] 麗貝卡 · 帕森斯 / [澳] 帕特里克 · 柯撰寫(xiě)的《演進(jìn)式架構》一書(shū),英文版在2017年10月出版。
對演進(jìn)式架構有如下這樣的關(guān)鍵說(shuō)法:An evolutionary architecture supports incremental, guided change as a first principle across multiple dimensions.
大體翻譯為“演進(jìn)式架構支持增量式并且引導式的變更,把它作為跨多維度的第一原則?!?/p>
此書(shū)識別了如下3個(gè)要素:
Incremental change -主要包含兩大部分,一個(gè)是軟件是如何增量構建,一個(gè)是它們是如何部署
Guided change with fitness functions - 用來(lái)指導如何進(jìn)行tradeoff來(lái)滿(mǎn)足選中的capability
Appropriate coupling - 需要根據不同的場(chǎng)景來(lái)進(jìn)行取舍耦合度,以最小的代價(jià)提供最好的收益而允許適度耦合。
本文第1版雖然寫(xiě)在《演進(jìn)式架構》一書(shū)之前,但正好與此書(shū)契合,本文描述重點(diǎn)在于演進(jìn),通過(guò)以下方面來(lái)說(shuō)明“演進(jìn)”的架構。
1, 架構的范圍
2, 初次架構
3, 架構文檔
4, 迭代中的架構
5, 推遲決策的架構
架構這詞起源于建筑領(lǐng)域,被延伸使用到了包括軟件領(lǐng)域的其它諸多領(lǐng)域?,F在只看軟件領(lǐng)域,就存在了許多種架構。我們常常會(huì )遇到不同形式的架構說(shuō)法,比如企業(yè)架構、系統架構、信息架構、應用架構、實(shí)現架構、基礎設施架構等。幾乎每種類(lèi)型的架構都圈了所覆蓋的架構范圍,而且都有擴大“地盤(pán)”的沖動(dòng)。眼下,軟件業(yè)界并沒(méi)有相互形式間的協(xié)定,導致對軟件架構同一詞語(yǔ)的不同理解。軟件架構考慮的范圍隨著(zhù)不同項目、不同團隊、不同系統,甚至于不同的時(shí)間段而不同。
對比原來(lái)常用的基本設計和詳細設計,架構一般不包含傳統的“詳細設計”,也不完全包含“基本設計”,而更加接近于“High Level Design”。一般而言。架構范圍不包括需求細節、用戶(hù)交互細節、類(lèi)的細節。
因此,對于特定團隊考慮進(jìn)行架構時(shí),值得首先就架構的范圍進(jìn)行討論,并達成初步的共識。當然架構范圍并不是從第一次達成共識后就不再變化,在架構演進(jìn)時(shí),團隊能夠就架構范圍進(jìn)行調整。
架構的范圍并沒(méi)有標準答案,以下是對于架構考慮范圍的推薦,最推薦的給5顆星,其次4、3、2。
· 支持的操作系統,比方 win7, Redhat9 ☆☆☆☆☆
· 支持的數據庫 比方Oracle, DB2, Mysql ☆☆☆☆☆
· 支持的瀏覽器(假設是有Brower訪(fǎng)問(wèn)的)☆☆☆☆☆
· 依賴(lài)的運行時(shí)環(huán)境 --比方Java, Silverlight ☆☆☆☆☆
· 依賴(lài)的中間件--- 比方Java容器,tomcat, websphere ☆☆☆☆☆
· 依賴(lài)的核心構件或者Frame, 比方springboot,struts, hibernate, 自己定義的構件 ☆☆☆☆☆
· 層次劃分,比方典型三層架構、多層架構,前后端分離 ☆☆☆☆
· 識別進(jìn)程,畫(huà)部署圖 ☆☆☆☆☆
· 劃分組件,畫(huà)組件圖 ☆☆☆☆☆
· 開(kāi)發(fā)語(yǔ)言 比方c#, java, c++ ☆☆☆☆☆
· 開(kāi)發(fā)所用的工具 比方IDE,報表設計器 ☆☆☆☆
· 重要組件間的接口 ☆☆☆☆
· 核心類(lèi)的設計 ☆☆☆
· 數據庫設計 ☆☆☆
· 核心流程的說(shuō)明 ☆☆
· 部分核心類(lèi)的類(lèi)圖 ☆☆
· 特別的性能要求帶來(lái)的考慮 ☆☆☆☆
· 特別的可恢復性要求帶來(lái)的考慮 ☆☆☆
· 特別的信息安全要求帶來(lái)的考慮 ☆☆☆
在系統早期,比方某系統的第0次迭代,或者重大升級,新接手某系統,需要進(jìn)行初次架構,需要理解系統的現狀、范圍、特征。
在架構關(guān)注的范圍內,哪些因素是硬性限制條件?哪些因素是可變限制條件?哪些因素是需要考慮解決的問(wèn)題?
一般地,全新開(kāi)發(fā)系統的限制條件比較少,需要考慮解決的問(wèn)題比較多,往往面臨“艱難的選擇”,當然這也是體現架構價(jià)值的地方。
所開(kāi)發(fā)的系統將或者已經(jīng)存在于環(huán)境中,那么其環(huán)境必定影響架構,所以需要考慮 “環(huán)境中的架構”?;旧?,環(huán)境決定了系統執行的范圍,這些又約定和限制了架構。影響架構的環(huán)境因素包括架構所支持的商務(wù)環(huán)境,系統涉眾群,內部技術(shù)限制(比如須要符合組織標準)。和外部技術(shù)限制(比如對外部系統的接口或遵守外部規則的標準)。
在此期間,鼓勵召開(kāi)架構的頭腦風(fēng)暴會(huì )議,討論系統的功能、性能等等特征,并思考實(shí)現這些特征的高層設計策略,甄別可行地技術(shù)策略。
依據這些了解、討論和思考,形成初始的架構文檔。
特別再次值得反復說(shuō)明的是:多數的架構是在已有軟件或系統上進(jìn)行的。原有軟件或系統將帶來(lái)原有的架構,這并不意味著(zhù)新項目能夠不再考慮架構。原有的架構可能不再適應當前的情況,而恰恰是須要改進(jìn)的地方。原有的架構或許非常好,不必改動(dòng),新開(kāi)發(fā)僅僅須要在其指定的架構下按部進(jìn)行就可以。原有的架構總體可行,局部需要調整,這樣的判斷本身就是架構。
在起草初始的架構文檔時(shí),值得充分理解并復用原有架構方面的文檔。
不管利用原有文檔,還是新寫(xiě),應當形成一套架構文檔,說(shuō)明團隊架構范圍內所關(guān)注的內容。這一套架構文檔要得到配置管理。
這套架構文檔的典型組成
1, 核心架構文檔(必需)
2, 接口文檔(對外接口,必需)
3。 模塊或子系統架構(可選)
4, 其他補充說(shuō)明(可選)
在迭代進(jìn)行中,架構文檔應當始終保持是一套文件,這套文件隨著(zhù)種種新情況、變更而得到演進(jìn)。但始終保持其全局性和及時(shí)性。
最值得注意的地方是要避免出現把新增改動(dòng)的內容寫(xiě)入特定版本號的架構文檔,這樣會(huì )導致組合多個(gè)文件才干反映架構總體情況。詳細而言,避免以下情況:
假設在第2個(gè)迭代結束后已經(jīng) 形成了 ABC架構文檔,在第3個(gè)迭代時(shí),當中某部分有重要改動(dòng)。 團隊為了明白這些是第3迭代的任務(wù)。也為方便的閱讀第3迭代的架構,把這部分改動(dòng)另寫(xiě)為ABC第3迭代架構文件。在第4個(gè)迭代時(shí)。又有某部分須要新增改動(dòng),然后有出現了ABC第4迭代架構文件,依此類(lèi)推。到第10個(gè)迭代時(shí),須要閱讀全部前面的架構文件才干了解全局,而不再有一份核心架構文檔就能反映全局。短期迭代的方便處理將損害長(cháng)期的架構演進(jìn)。
因此。演進(jìn)的架構必須利用版本控制工具,以前推薦了諸如CVS,SVN,ClearCase等來(lái)管理架構文檔,最新推薦帶有自動(dòng)版本記錄的線(xiàn)上化工具,比如Confluence,騰訊文檔等等。線(xiàn)上化工具支持多人線(xiàn)上協(xié)同,使用效率遠遠超過(guò)了把word文件存放到Git。
通過(guò)這類(lèi)工具的幫助,在不論什么時(shí)間點(diǎn),都能及時(shí)地展現的一套架構文檔,也能追隨到老版本,還能比對前后差異。為增量式演進(jìn)提供了巨大便利,或者說(shuō)這是增量式演進(jìn)所必需的。
在迭代開(kāi)發(fā)當中,在每一個(gè)迭代的前期甚至提前一個(gè)迭代,結合最新業(yè)務(wù)需要來(lái)考慮對于架構的影響。
如果對于原有架構文檔有變化,就應當修訂架構文檔。在演進(jìn)中,對于架構最常見(jiàn)的兩大影響是
1,模塊的改動(dòng)和新增,包括外接新系統;
2,因為時(shí)間推移所帶來(lái)的容量方面的問(wèn)題,一般最突出的是性能問(wèn)題。值得密切注意模塊之間的交互。
推薦提問(wèn):
1, 這個(gè)迭代是否要新增模塊?
2, 是否對已經(jīng)存在的模塊有改動(dòng),模塊之間的交互是否有變化?
3。 與其他系統的交互是否有變化?是否須要與新系統通訊?
4。 能否夠支持容量方面的情況?比如訪(fǎng)問(wèn)量?比方硬盤(pán)容量?帶寬?CPU?
另外可能的變化是團隊對于架構范圍的理解可能變化,依據變化后的架構范圍理解,增補架構文檔的內容。
值得再強調的是迭代中不僅僅可以對架構范圍進(jìn)行調整,也可以對之前的架構決策進(jìn)行調整,這就是演進(jìn),而不是如同建筑的架構不可調整。
還有一個(gè)因素值得強調-迭代的顆粒度,哪怕采用長(cháng)達4周的迭代,對比原來(lái)基本設計+詳細設計做法對應的時(shí)間顆粒度,也是有幾倍的差距。原來(lái)講究基本設計+詳細設計的情況下,對應交付版本間隔長(cháng)達4個(gè)月以上,甚至更久。
當下常見(jiàn)的迭代長(cháng)度是2到3周,領(lǐng)先企業(yè)有采用1周迭代周期,也有無(wú)迭代做法,交付版本間隔常見(jiàn)也在2到3周,領(lǐng)先企業(yè)更加快。 在這樣情況下,有一個(gè)形象的比喻是給行駛中的汽車(chē)換個(gè)輪子,不會(huì )再有安排一個(gè)長(cháng)達3周的設計階段來(lái)做設計。
因此原來(lái)基本設計+詳細設計的做法不能簡(jiǎn)單放入短迭代開(kāi)發(fā),需要經(jīng)過(guò)裁剪后才能很好的指導迭代開(kāi)發(fā)。
在演進(jìn)的架構中值得推遲決策,推遲決策并非指到最后才決定做什么,而是要盡量推遲決策,以更靈活的應對不確定性。
當出現架構決策時(shí),考慮例如以下提問(wèn):
· 當前必須制定這個(gè)決策嗎?
· 能夠安全地推遲這一決策嗎?
· 能做些什么使決策可逆?
· 能否夠先進(jìn)行些嘗試,以幫助決策?
在演進(jìn)的架構下,也為決策的推遲提供了便利。當前迭代涉及的架構問(wèn)題是須要立即給出方案的,對于興許的架構問(wèn)題是有機會(huì )推遲決策的。當然這里是有長(cháng)期考慮和短期考慮的權衡,并非說(shuō)演進(jìn)的架構下僅僅須要考慮本迭代的架構問(wèn)題。但也不是說(shuō)須要考慮全部興許迭代的架構問(wèn)題。
對比傳統架構設計,往往假設架構有長(cháng)時(shí)間指導意義,比較穩定,因此需要慎重,花費專(zhuān)門(mén)大段時(shí)間來(lái)進(jìn)行架構設計。
在延遲決策的架構策略下,恰恰得到相反的論斷:在剛剛開(kāi)始時(shí),沒(méi)有必要安排超過(guò)迭代周期的、專(zhuān)門(mén)的架構設計階段或迭代。在演進(jìn)的背景下,預先花費大量時(shí)間的所謂設計階段是多余的。
因為這個(gè)世界變化太快,提早的架構往往想得太美,不如采用演進(jìn)的做法,在迭代增量當中逐漸追求并且逼近完美。
另外值得說(shuō)明的一點(diǎn)是推遲決策不是等到代碼寫(xiě)得差不多了,再來(lái)補架構設計文檔!如果是代碼寫(xiě)得差不多了,那只能是為了文檔合規要求而寫(xiě)文檔,喪失了架構設計的意義。架構應當在前面指導代碼編寫(xiě),也敢于留出空白讓一線(xiàn)程序員發(fā)揮。
---全文玩---
聯(lián)系客服