屬性驅(qū)動設(shè)計是目前最全面最廣泛使用的有文檔記錄的軟件架構(gòu)設(shè)計方法,簡稱ADD。在ADD第一次出現(xiàn)時,他是一個特別側(cè)重于質(zhì)量屬性,并且通過創(chuàng)建軟件架構(gòu)的結(jié)構(gòu)方式來實現(xiàn)他們,通過視圖來表示他們的設(shè)計方法。它把軟件架構(gòu)分析和文檔作為設(shè)計過程的一個重要組成部分。在ADD中,設(shè)計活動包括提煉早期設(shè)計迭代過程中創(chuàng)建的草圖來產(chǎn)生一個更詳細的架構(gòu),并不斷對設(shè)計進行評估。
在ADD2.0發(fā)布時,對于如何將質(zhì)量屬性和設(shè)計選擇相關(guān)關(guān)聯(lián)起來非常有用,但仍舊有一些缺點:
- ADD2.0指導(dǎo)架構(gòu)師使用并將策略和模式組合在一起以實現(xiàn)令人滿意的質(zhì)量屬性場景,但是模式和策略比較抽象,沒有解釋如何去映射成具體的技術(shù)
2.ADD2.0在敏捷開發(fā)之前發(fā)布,所以沒有關(guān)于敏捷開發(fā)環(huán)境的指導(dǎo)。 - 沒有提供如何開始設(shè)計過程的指導(dǎo)。
- 沒有處理一些架構(gòu)關(guān)注點、考慮不同的設(shè)計目標(biāo)。
。。。。
在ADD3.0中,以上的這些都解決了,對于敏捷開發(fā)中,ADD3.0推廣的是快速設(shè)計迭代,在每個迭代盡量做出少的設(shè)計決策,可能是一個實現(xiàn)的重建增量。
在ADD3.0中推廣了使用參考架構(gòu),并與設(shè)計概念目錄配對,該目錄中包括一個各種戰(zhàn)術(shù),模式,框架,參考架構(gòu)和技術(shù)的選集。
在看這篇文章之前,里面有很多專業(yè)性名詞解釋,建議先看下這篇文章,對一些架構(gòu)相關(guān)和屬性驅(qū)動設(shè)計相關(guān)的概念能有一個入門性的認識,方便后面的學(xué)習(xí):
ADD3.0屬性驅(qū)動設(shè)計之基礎(chǔ)
屬性驅(qū)動設(shè)計的架構(gòu)設(shè)計過程

1.步驟一: 評審輸入
首先需要確保設(shè)計流程的輸入是可用且正確的,先確認設(shè)計目的是否符合設(shè)計的類型,確保設(shè)計過程中其他的屬性驅(qū)動因子也是可用的,最后,如果是設(shè)計一個綠地系統(tǒng),還需要已經(jīng)存在的架構(gòu)設(shè)計的輸入存在是否合理。
(注: 架構(gòu)驅(qū)動因子包含: 設(shè)計目的、質(zhì)量屬性、主要功能、架構(gòu)關(guān)注點、約束條件等等,詳情我后面會說)
驅(qū)動因子成了架構(gòu)設(shè)計待辦列表的一部分,需要用他們來完成不同的迭代目標(biāo)。
2.步驟二: 通過選擇驅(qū)動因子(架構(gòu))建立迭代目標(biāo)
根據(jù)使用的開發(fā)模型去選擇設(shè)計的回合。
如果是迭代開發(fā)模型,設(shè)計回合指在開發(fā)周期內(nèi)所執(zhí)行的架構(gòu)設(shè)計活動,如果是瀑布模型,設(shè)計回合指代的是全套架構(gòu)設(shè)計活動。通過一個或者多個回合,產(chǎn)生一個符合已建立設(shè)計目的架構(gòu)。
一個設(shè)計回合需要在一系列的設(shè)計迭代中進行,每一個迭代著重完成一個目標(biāo),特別是滿足驅(qū)動因子的目標(biāo)。舉個例子: 一個迭代的目標(biāo)可能是創(chuàng)建源自元素的結(jié)構(gòu),這些元素會支持特殊的性能場景,或者啟動一個即將完成的用例。
3.步驟三: 選擇一個或者多個系統(tǒng)元素來細化
(注: 這里的元素是指軟件模塊、整個軟件系統(tǒng)包含多少個元素或者說子模塊,電商軟件系統(tǒng): 訂單、庫存、支付、前臺、用戶等等元素)
需要滿足驅(qū)動因子需要產(chǎn)生一個或者多個架構(gòu)結(jié)構(gòu),這些結(jié)構(gòu)是由具有內(nèi)在關(guān)聯(lián)的元素組成的,并且這些元素通常是經(jīng)過細化前在之前的迭代中確定的元素獲得的。
細化就是分解成細?;脑亍⒔M合成粗粒度的元素或者對之前確定好的元素進行細化。
4.步驟四: 選擇一個或者多個設(shè)計概念(就是架構(gòu)設(shè)計模式)以滿足選中的驅(qū)動因子.
架構(gòu)設(shè)計模式包括結(jié)構(gòu)模式: 分層設(shè)計、域?qū)ο笤O(shè)計。接口分區(qū):顯示接口,代理。 基于高并發(fā)得設(shè)計: 半異步/半同步設(shè)計。后面會詳細介紹。
5.步驟五:實例化架構(gòu)元素、分配職責(zé)和定義接口
選擇好了一個或者多個設(shè)計概念,就要另作一個設(shè)計決策了,包括所選擇的實例化元素的設(shè)計概念。如果選擇分層,需要決定分多少層,在這里例子中,這些分層就是實例化后的元素,某些情況下,實例化是可以配置的。
在實例化元素之后,需要給每個元素分配職責(zé)。舉個例子: 在據(jù)于網(wǎng)絡(luò)的企業(yè)級系統(tǒng)中,通常有三層:表示層、業(yè)務(wù)層、數(shù)據(jù)層。
實例化元素只是一個任務(wù),這個任務(wù)通過開展創(chuàng)建架構(gòu)以滿足一個驅(qū)動因子或者一個關(guān)注點。已經(jīng)被實例化后的元素也需要被關(guān)注起來,一遍這些元素之間可以互相配合。通過接口來實現(xiàn)交互。
6步驟六: 草擬視圖和記錄設(shè)計決策
到了這一步,已經(jīng)完成了該迭代中所執(zhí)行的設(shè)計活動了??赡苣氵€沒有采用任何行動來確保結(jié)果視圖能夠被保留。你創(chuàng)建好的視圖肯定不是完整的,在隨后的迭代中這些圖可能還需要重新被審視和細化。通常這樣做是為了調(diào)整其他設(shè)計決策產(chǎn)生的元素,這些設(shè)計決策還需要支持其他的驅(qū)動因子,這個就解釋了,我們在ADD方法中,強調(diào)手稿,代表創(chuàng)建初期。
7:步驟七: 分析當(dāng)前設(shè)計、評審迭代目標(biāo)、實現(xiàn)設(shè)計目的
目前已經(jīng)創(chuàng)建好了部分設(shè)計,此時已經(jīng)可以得到這個迭代設(shè)計建立的目標(biāo)。徐奧確保這個目標(biāo)是一個好想法,可以得到項目利益相關(guān)者的認同,避免否定,導(dǎo)致返工。此時可以自己繼續(xù)展開分析或者找人幫助評審。
一旦在迭代中執(zhí)行的設(shè)計進行了分析,此時你就可以根據(jù)既定的目標(biāo)來評審你的架構(gòu)狀態(tài)。這意味著,你已經(jīng)進行了足夠的設(shè)計迭代,已滿足與設(shè)計回合相關(guān)的驅(qū)動因子,以及考慮設(shè)計目標(biāo)是否已經(jīng)實現(xiàn)了,或者在未來項目增量中,是否需要額外的回合。
最后一步: 按需迭代
理想狀態(tài)下,對每一個被稱為輸入組成之一的驅(qū)動因子,都要執(zhí)行額外的迭代,并重復(fù)執(zhí)行步驟2-7.通常情況下,這樣的迭代不太可能出現(xiàn),因為時間或資源的限制,會迫使你停止設(shè)計活動。
對于是否需要更多的迭代,可以讓風(fēng)險來評估。怎么說呢?我們至少找到更高優(yōu)先級的驅(qū)動因子,理論上,應(yīng)該確保關(guān)鍵驅(qū)動因子是被滿足的,或者至少設(shè)計了足夠好的滿足驅(qū)動因子,最后實施時,能夠在每個項目迭代中,執(zhí)行一個設(shè)計回合。第一回合把重點放在定位驅(qū)動因子上,隨后再為其他回合指定設(shè)計決策。
根據(jù)系統(tǒng)設(shè)計類型遵循設(shè)計路線圖
一般來說,軟件系統(tǒng)的設(shè)計分為三大類:
1. 一個成熟領(lǐng)域內(nèi)的綠地系統(tǒng)設(shè)計。

舉個例子: 比如非常常見的電商購物系統(tǒng)、CRM等企業(yè)級系統(tǒng),都是在領(lǐng)域內(nèi)很成熟的,并且常見的架構(gòu)關(guān)注點也總所周知,十分常見??梢园凑丈蠄D的步驟來實現(xiàn)。
最初的迭代目標(biāo)應(yīng)該是,解決建立一個初步完整的整體系統(tǒng)體系架構(gòu)的常見關(guān)注點,是一個瀏覽器到服務(wù)器的一個應(yīng)用程序或者移動端到服務(wù)端。這些選擇會讓你建立不同的架構(gòu)解決方案,并且這些解決方方案將有不同的實現(xiàn)驅(qū)動因子。
具體而言,為了實現(xiàn)設(shè)計目標(biāo),,需要選擇設(shè)計概念,會選擇一個或多個參考架構(gòu)和部署模式,還有一些外部開發(fā)組件比如spring框架等。
在第一期迭代,需要評審所有的驅(qū)動因子來選擇設(shè)計概念,也需要注意約束條件和質(zhì)量參數(shù)。
接著的迭代目標(biāo),應(yīng)該是識別那些支持主要功能的結(jié)構(gòu),對功能進行分配,一旦功能被分配好了,支持功能的元素可以在之后的迭代階段,支持與這些功能關(guān)聯(lián)的質(zhì)量參數(shù)。例如選擇一個web應(yīng)用程序參考體系結(jié)構(gòu),支持的用例可能需要識別模塊,這些模塊貫穿在與參考架構(gòu)關(guān)聯(lián)的不同分層中,最后,在這一點上,也應(yīng)該考慮哪些與模塊相關(guān)的功能分配,要分配到開發(fā)團隊中去。
之后的迭代目標(biāo),應(yīng)該是完善細化之前創(chuàng)建的結(jié)構(gòu),以完全解決剩余的驅(qū)動因子,特別是質(zhì)量屬性。
2. 一個新領(lǐng)域內(nèi)的綠地系統(tǒng)設(shè)計。
在新興領(lǐng)域的例子中,比較有挑戰(zhàn)性的是建立一個精確的路線圖。這塊的設(shè)計路線圖,沒辦法詳細說明,還是基于屬性驅(qū)動設(shè)計的思路:
迭代的目標(biāo)主要還是不斷完善和細化以前創(chuàng)建的結(jié)構(gòu),以充分解決這些驅(qū)動因子。
3.對現(xiàn)有系統(tǒng)的更改設(shè)計(棕地系統(tǒng)設(shè)計)。
現(xiàn)存系統(tǒng)架構(gòu)設(shè)計的目的不同,最顯而易見的是保留,就是說在滿足新需求和修復(fù)bug的時候,需要改變現(xiàn)有的系統(tǒng)架構(gòu),我們在ADD方法的步驟三中說明了,需要選擇元素已將其分解為設(shè)計過程的一部分,首先需要確定哪些元素存在于現(xiàn)有的系統(tǒng)架構(gòu)中,從這個意義來說,在開始設(shè)計迭代之前,第一個目標(biāo),需要先對現(xiàn)有系統(tǒng)的架構(gòu)有非常清晰的認識。
一旦你理解了元素、屬性、構(gòu)成系統(tǒng)架構(gòu)的關(guān)系,以及現(xiàn)存代碼庫的屬性,在初始設(shè)計迭代之后,就可以執(zhí)行類似于下面面對綠地系統(tǒng)的設(shè)計。
設(shè)計目標(biāo)應(yīng)該是確定和改進結(jié)構(gòu),以滿足架構(gòu)驅(qū)動因子,包括新的功能和質(zhì)量參數(shù),以及解決特定的架構(gòu)問題關(guān)注點,包括新的功能和質(zhì)量參數(shù),以及解決特定的架構(gòu)問題。
如何設(shè)計和選擇設(shè)計概念
設(shè)計概念的識別是很艱難的,因為世界上有很多的設(shè)計概念,可能有幾十個設(shè)計模式和外部開發(fā)組件,能夠用來解決特定的具體問題。
在設(shè)計過程中的不同環(huán)節(jié)一般需要不同類型的設(shè)計概念,比如設(shè)計成熟領(lǐng)域的綠地系統(tǒng)時,有助于初步構(gòu)建系統(tǒng)設(shè)計概念類型的是參考架構(gòu)和部署模式。
隨著設(shè)計過程的進行,將使用所有的設(shè)計概念類型: 決策,架構(gòu)和設(shè)計模式、外部開發(fā)組件。一般來說,為了解決一個特定的設(shè)計問題,都會使用各種不同的設(shè)計概念組合起來。
一旦對需要使用的設(shè)計概念有清晰的理解之后,還需要一個確認一個替換方案---就是設(shè)計的候選方案。
在識別和選擇設(shè)計概念時,也要考慮約束因子,這也是架構(gòu)驅(qū)動因子的一部分,某些條件可能會限制你選擇特定的替換方案。
最后還需要記住,ADD這種方式只是對如何執(zhí)行設(shè)計過程提出了指導(dǎo),并不意味著能確保你做出合適的設(shè)計決策。
架構(gòu)結(jié)構(gòu)的生成
設(shè)計概念對滿足驅(qū)動因子本身沒有幫助,除非構(gòu)建出架構(gòu)來,也就是說,需要識別并選定設(shè)計概念的元素,在ADD方法中,這個過程其實就是架構(gòu)元素實例化,建立元素與元素之間的關(guān)系,給這些元素分配不同的職責(zé).需要清楚,一個軟件系統(tǒng)應(yīng)該是由一組結(jié)構(gòu)組成的,這些結(jié)構(gòu)可以分成三大類:
1、模塊結(jié)構(gòu)
由開發(fā)期間的邏輯和靜態(tài)元素組成,如文件、模塊以及類。
2、組件和連接器結(jié)構(gòu)
由運行時存在的動態(tài)元素組成,如進程和線程
3、分配結(jié)構(gòu)
由兩個軟件元素(來自于C&C結(jié)構(gòu))以及非軟件元素組成,非軟件元素一般存在于開發(fā)期間也存在
于運行期間,如文件系統(tǒng)、硬件以及開發(fā)團隊。
實例化設(shè)計概念時,可能生成不止一個結(jié)構(gòu)。例如,在某個特定的迭代中,實例化分層模式,生成一個模塊結(jié)構(gòu)。作為實例化該模塊的一部分,選擇分層數(shù)量、層與層之間的關(guān)系,以及每一層的職責(zé),作為迭代的一部分,也可以研究場景是如何由元素支撐起來的,這些元素就是你剛剛確定下來的那些。例如,可以在C&C建立一個邏輯元素的實例,模擬邏輯元素交換的信息。最后要決定誰來負責(zé)實施每一層內(nèi)的模塊,稱之為分配決策。
需要以下步驟:
1. 把架構(gòu)元素實例化
架構(gòu)元素方面的實例化,取決于你正在制定的設(shè)計概念的類型:
參考架構(gòu): 在參考架構(gòu)的情況下,實例化就需要實施某些定制化,增加或者刪除某些元素。比如如果是個web應(yīng)用程序,在處理支付相關(guān)操作時,需要跟一個外部應(yīng)用程序進行通信,除了正常的MVC層之外,還需要一個集成層。
架構(gòu)和設(shè)計模式: 實例化通常涉及到由模式定義的通用結(jié)構(gòu)的轉(zhuǎn)換,轉(zhuǎn)換到特定的結(jié)構(gòu)。
部署模式:部署模式的實例化通常涉及物理元素的識別和規(guī)范,比如部署的集群的數(shù)量,負載均衡策略,算法,和副本的位置等等。
策略: 策略這個設(shè)計概念沒有特定的結(jié)果,所以需要使用其他設(shè)計概念來實例化策略,比如你選擇一種角色驗證的安全策略,可以創(chuàng)建一個臨時編碼來實例化該策略,也可以通過安全模式或者使用外部開發(fā)安全框架來實現(xiàn)。
第二步: 劃分職責(zé)和識別屬性
通過實例化設(shè)計概念和創(chuàng)建元素時,需要考慮給這些元素分配職責(zé)。比如如果是實例化分層模式并且使用傳統(tǒng)的三層時,還需要考慮其中一個分層負責(zé)處理用戶交互,這是表示層,在實例化元素和分配職責(zé)時,切記系統(tǒng)邊界的問題,高內(nèi)聚/低耦合的設(shè)計原則,元素需要具有高內(nèi)聚,比如通過小范圍的職責(zé)定義,還要保持低耦合,不用通過了解其他元素來實現(xiàn)業(yè)務(wù)細節(jié)。
在設(shè)計化實例概念時,需要考慮另一個方面的元素的屬性,這可能包括比如一些配置的選項,狀態(tài)性,資源管理,優(yōu)先級,識別這些屬性來幫助分析和維持設(shè)計原理文檔。
最后要建立元素之間的關(guān)系
架構(gòu)創(chuàng)建還需要對元素和元素屬性之間存在的關(guān)系做出決策。然后,可以考慮分層模式。你可以決定把兩層連接起來,但是這些層,終將會分配在不同的機器上,此時你可以涉及如何進行通信,選擇的哪種通信協(xié)議,進行異步通信還是同步通信?這些都會對生成的具體的質(zhì)量屬性有明顯的影響,如性能等屬性。
設(shè)計過程中第五步: 定義接口
接口是我們元素的外部可見屬性,這些元素建立了一個允許元素合作和交換信息的規(guī)范。接口有兩種類型: 內(nèi)部的和外部的。
外部接口: 正在開發(fā)的系統(tǒng)需要其他外部的其他系統(tǒng)提供的接口,以及我們提供給外部系統(tǒng)的接口。
內(nèi)部接口是設(shè)計實例化概念設(shè)計結(jié)構(gòu)產(chǎn)生的元素之間的接口,要實現(xiàn)接口間的關(guān)系和細節(jié),通常需要了解運行時如何交換信息,這需要建模工具來理解,可以使用UML工具中的序列圖來對執(zhí)行過程中元素的交互信息進行建模,來支持用例和質(zhì)量屬性方案,這種類型的分析也有利于識別元素間的交互關(guān)系。