《系統架構》讀書筆記:架構到底是什麼?
作者 | 章燁明
杏仁醫生CTO。中老年程式員,關注各種技術和團隊管理。
引子
這個月讀了一本書,《系統架構》。然而這本書講的不僅僅是軟體系統的架構,而是更高一個層面,它講的是複雜系統的架構。這本書的三位作者,有兩位是航空航天專業的教授和副教授,所以書裡用了不少 NASA 的專案為案例,比如人類有史以來最複雜的工程——阿波羅計劃。讀完這本書,讓我對架構的認識提升了一個高度,原先各種離散的關於架構的知識和理解,在這個框架下,終於可以融會貫通了。
系統和系統思維
首先,系統是什麼?按本書的定義,系統是由一組實體和這些實體之間的關係所構成的集合,而其功能要大於這些實體各自的功能之和。後半句很重要,如果一個系統的功能,等於其部件的功能之和,那麼這個系統就沒有存在的意義。因為我們單獨使用那些部件,也可以得到需要的功能。只有當這些部件組合時,能夠湧現出新的功能,那才算是組成了一個系統。
要理解系統架構,首先要有系統思維。所謂系統思維,就是把某個疑問、某種狀況或某個難題明確地視為一個系統,也即是視為一組相互關聯的實體,而不是孤立的一個物件。
系統思維要有四個步驟是:
-
確定系統整體的形式與功能。
-
確定系統中包含的元件,元件的形式與功能。
-
確定系統中各個元件之間的關係,並且定這些關係的形式及其功能。
-
根據元件的功能及功能性的互動來確定系統的湧現屬性。
系統思維的初級目標是理解系統是什麼,更進一層的目標是為了預測系統在發生某些變化之後的情況。而最高階的目標,則是用部件來合成一個系統,這個過程也就是所謂的系統架構。
系統架構的分析
形式與功能
形式是系統的物理體現或資訊體現,它有助於功能的執行。形式可以分為形式物件,以及這些形式物件之間具有的形式關係(也就是結構)。例如,汽車作為一個系統,它的形式物件就是汽車部件,而軟體系統的形式物件則是模組、過程、程式碼和指令,而這些形式物件則通過不同的結構組裝成一個系統。
系統的另一個屬性就是功能。功能由過程和操作物件組成,過程在操作物件上執行之後,會改變操作物件的狀態。當系統對外展現的功能對系統的外部的物件進行操作時,系統的價值就體現出來了。例如,離心泵中的電動機可以帶動葉輪旋轉,這是它內部的一個功能。而離心泵作為一個系統,它可以給外部物件(例如某種液體)加壓,從而移動液體。這也就是它的功能和價值所在。
形式和功能的區別就是,形式決定了系統是什麼,而功能決定了系統能做什麼。架構其實就是形式與功能之間的對映。形式結構對功能起著承載作用,或者能夠促進相關的效能。在複雜系統裡,形式與功能的對映會非常複雜,包含很多不確定的問題,或者非理想的因素。因此架構師需要使用抽象等方法來簡化架構,以便能夠更好的理解和交流架構。
另外,還有一種特殊的功能,叫做解決方案無關的功能。例如,我要從上海出差去北京,那麼“將旅客從上海快速、安全的運送到北京”就是解決方案無關的功能,而“使用高鐵/飛機將旅客從上海運送到北京”則不是。好的系統規範書,應該是使用與特定解決方案無關的功能來描述的。如果系統規範書將人引導向某種具體的解決方案,可能會令架構師的視野變窄,從而不去探索更多的潛在選項。
從概念到架構
前面說過,架構就是功能與形式之間的對映,但對於複雜系統,這種對映往往非常複雜。架構師常常需要創造一些概念,來簡單明瞭的解釋功能是如何對映到形式的。例如前面離心泵的例子,它的解決方案無關的功能則是“移動液體”,而離心泵本身其實就是一個概念,一提到離心泵,熟悉的人一定會想到電動機、葉輪等等。其他的概念包括油電混動、高速鐵路、發光二極體、快速排序、分散式快取等等。軟體開發中的各種設計模式,其實也是概念。
對於一個解決方案無關的功能,往往能提出多個不同的概念。架構師需要創造性地提出這些概念,對它們進行整理,並選定其中一個概念,將其轉化為一套架構。
複雜系統的架構往往是分層的,同時我們還需要對架構進行模組化。需要注意的是,如果要對某一層的架構進行模組化,我們必須將其分解到下一層。因為只有檢查各個實體在更下一層的關係,才能更好的對當前層級進行模組化。
建立系統架構
架構師
很多人常常會問,架構師的職責到底是做什麼?這本書給出了很明確的回答,架構師的職責主要是以下三個方面:
-
減少歧義,確定系統的邊界、目標和功能
-
發揮創造力,建立概念
-
管理複雜度,為系統選定一種分解方案
而架構師的交付成果,應該包括:
-
一套清晰、完整、連貫的目標,並且是可行的(80% 以上概率)。
-
系統所在的大環境(法律法規、行業規範等等)以及整個產品環境的描述。
-
系統的概念以及操作方式。
-
系統的功能描述(至少兩層分解),除了系統對外界展現的功能,也包括系統的內部功能。
-
系統的形式(至少兩層分解)和形式結構,以及功能和形式之間的對映。
-
所有的外部介面以及介面控制過程的詳細描述。
-
開發成本、工期、風險、實現計劃等。
消除歧義,確定目標
為了消除歧義,架構師必須首先理解上游和下游的相關因素對系統架構的影響。上有因素包括:公司策略、營銷、法律法規、行業標準、技術成熟度等,下游因素包括實現(編碼、製造、供應鏈管理)、操作、產品與系統的演化。
複雜的系統一般會涉及多個的利益相關者,他們會有不同的訴求和目標,架構師需排定各專案標之間的優先次序。首先,可以把價值視為一種交換,在交換過程中,我方的成果用來滿足對方的需求,而對方的成果也同樣用來滿足我方的需求。其次,可以根據利益相關者對本產品的重要程度,來排列其優先次序。最後,則可以把系統的目標,展示在系統問題描述中(System Problem Statement, SPS)。
發揮創造力,建立概念
接下來,架構師就需要發揮創造性、建立概念了。創造概念,主要有兩種方式,一種是無結構的方式,一種是結構化的方式;無結構的創新包括頭腦風暴法、自由聯想法等方法。對於一些包含多個功能的豐富概念,我們可以對其進行擴充套件和分解,提出對應的概念片段,而這些概念片段組合後,又會形成新的整體概念。最後通過定量和定性分析,篩選出 2~3 個作為候選概念。
管理複雜度,為系統選定一種分解方案
架構師另外一項工作,就是分解系統,管理複雜度。系統的表面複雜度就是系統的難懂程度,表面複雜度高的系統理解起來會比較困難。架構師可以通過抽象、層級化、分解及遞迴等手段來減少表面複雜度,但這樣做可能會提升實際複雜度。其中架構師最重要的一項決策,就是對系統進行的分解。要判斷一種分解方式好不好,必須先向下分解兩層,並根據第二層的分解情況,來檢查第一層的分解方式是否合適。另外,架構師也要選擇合適的分解平面,例如可以按功能分解、按形式分解、按模組變化程度分解、按供應商分解等等。
架構決策
其實架構方面的決策也可以用一些程式化的方法進行計算,以幫助架構師進行決策,這部分比較枯燥就不細說了。不過書中提到架構決策的模式,還有點意思,一共有六個模式:
-
Decision-Option(決策-選項):一組決策,每個決策都有一套離散選項。例如,開始一個系統需要做一下兩個決策,決定資料庫和 API 介面的使用何種技術:資料庫是用 SQL/">MySQL、MongoDB 還是 Cassandra,API 介面是用 HTTP 還是 Protobuf。這就是一個 Decision-Option 決策。
-
Down-Selecting(篩選):一組二選一的決策,代表選擇實體中的某個子集。例如,我要從全國各地的 候選 IDC 機房中,選擇合適的機房來部署 CDN,就是一個 Down-Selecting 決策。
-
Assiging(指派):把一個實體集中的元素,指派給另一個實體集中的某個或某些元素。
-
Partitioning(分割槽):把一個實體集的元素劃分為多個互斥的子集,並且覆蓋所有元素。這是模組分解的典型決策模式。
-
Permuting(排列):在一個實體集和一個位置集之間建立一一對應關係。
-
Connecting(連線):給定一個用圖中節點表示的實體集,用一組連線展示這些節點之間的關係。網路拓撲結構的決策就是一個 Connecting 問題,即選擇星形拓撲、環形拓撲或者匯流排拓撲等等。
書裡用了一個很牛逼的例子——阿波羅計劃,來說明架構決策的方案。
總結
看完這本書,你會發現,其實所有的架構,軟體也好、汽車飛機等各種機器的架構也好,都是相通的。甚至我各種生物組織、團隊組織的架構,也是一樣的道理。只要我們能掌握系統架構的思維,再加上各個領域的專業知識,我們就能做出一套優秀的架構。
系統架構原則
書中最後總結了系統架構的二十六個原則,我摘錄在這裡供大家參考:
湧現原則:當各實體拼合成一個系統時,實體之間的互動會把功能、行為、效能和其他內在屬性現出來。
整體原則:每個系統都作為某一個或某些個大系統的一小部分而運作,同時,每個系統中也都包含著更小的一些系統。
聚焦原則:在任何一個點上都能發現很多影響系統的問題,而其數量已經超出了人們的理解能力。因此,我們必須找出其中最關鍵、最重要的那些問題,並集中精力思考它們。
二元原則:所有由人類構建而成的系統,其本身都同時存在於物理領城和資訊領域中。
受益原則:好的架構必須使人受益,要想把架構做好,就要專注於功能的湧現,使得系統能夠把它的主要功能通過跨越系統邊界的介面對外展示出來。
價值與架構原則:價值是有著一定成本的利益。架構是由形式所承載的功能。由於利益要通過功能而體現,同時形式又與成本相關,因此,這兩個論述之間形成一種特別緊密的聯絡。
與特定解決方案無關的功能原則:糟糕的系統規範書總是把人引向預先定好的某一套具體解決方案、功能或形式中,這可能會令系統架構師的視野變窄,從而不去探素更多的潛在選項。
架構師角色原則:架構師的角色是解決歧義、專注創新,並簡化複雜度。
歧義原則:系統架構的早期階段充滿了歧義。架構師必須解決這種歧義,以便給架構團隊定出目標,並持續更新該目標。
現代實踐壓力原則:現代產品開發過程是由同時工作著的多個分散式團隊來進行的,而且還有供應參與,因此,它更加需要有優秀的架構。
架構決策原則:我們要把架構決策與其他決策分開,並且要提前花一些時間來道慎地決定這些問題,因為以後如果想變更會付出很高的代價。
遺留元素複用原則:要透相地理解遺留系統及其現屬性,並在新的架構中把必要的遺留元素包據進來。
產品進化原則:系統必須進化,否則就會失去竟爭力。在進行架構時,應該把系統中較為穩固的部分定義為介面,以便給元素的進化提供便利。
開端原則:在產品定義的早期階段列出的(企業內部和企業外部的)利益相關者會對架構產生極其重大的影響。
平衡原則:有很多因素會影響並作用於系統的構想、設計、實現及操作,架構師必須在這些因素中尋求一個平衡點,使大多數重要的利益相關者得到滿足。
系統問題陳述原則:對問題所做的陳述會確定系統的高層目標,並劃定系統的邊界。就問題陳述的正確性進行反覆的辯論和完善,直到你認為滿意為止。
歧議與目標原則:架構師必須解決這些歧義。以便提出幾條有代表性的目標並持續地更新它們。這些目標要完備且一致,要兼具挑戰性和可達成性,同時又要能夠為人類所解決。
創新原則:在架構中進行創新,就是要追求一種能夠解決矛盾的好架構。
表面複雜度原則:我們要對系統進行分解、抽象及分層,將其表面複雜度控制在人類所能理解的範圍。
必備複雜度原則:系統的必備複雜度取決於它的功能,把系統必須實現的功能仔細描述出來。然後選擇一個複雜度最低的概念。
第二定律原則:系統的實際複雜度總是會超過必備複雜度。架構師要令實際複雜度儘量接近必備複雜度。
分解原則:分解是由架構師主動做出的選擇。分解會影響效能的衡量標準,會影響組織的運作了式及供應商的價值捕獲潛力。
二下一上原則:要想判斷出對 Level1 所做的分解是否合適,必須再向下分解一層,以確定 Level2 的各種關係。
優雅原則:對於身處其中的架構師來說。如果系統的必備複雜度較低,而且其分解方式能夠同與多個分解平面相匹配,那麼該系統就是優雅的。
架構健壯程度原則:好的架構要能夠應對各種各樣的變化。能夠應對變化的那種架構,要麼是比較健壯架構。要麼是適應能力比較強的架構。前者能夠處理環境中的變化,而後者則能夠適環境中的變化。
架構決策的耦合與整理原則:可以按照指標對決策的敏感度以及決策之間的連線度來排定架構決策之間的先後順序。
全文完
以下文章您可能也會感興趣:
我們正在招聘 Java 工程師,歡迎有興趣的同學投遞簡歷到 [email protected] 。
杏仁技術站
長按左側二維碼關注我們,這裡有一群熱血青年期待著與您相會。