圖重構(gòu):用C4模型厘清系統(tǒng)邊界與依賴)
前陣子接手一個歷史項目代碼能跑但團隊里沒人說得清“這個服務(wù)為什么在這里”“那兩個模塊之間到底是什么關(guān)系”。每個人腦子里都有一張不同的架構(gòu)圖開會各說各話。這大概是很多團隊的真實狀態(tài)。今天我們聊的就是“架構(gòu)圖重構(gòu)”這第一筆——不是用畫圖軟件把舊圖重繪一遍而是用一張圖把系統(tǒng)的真實邊界、依賴和決策重新串起來。這也是“架構(gòu)師覺醒從重構(gòu)到引領(lǐng)”系列第2集的核心架構(gòu)師不必記得每條代碼路徑但必須能在畫布上用第一筆把系統(tǒng)的骨架和邊界表達清楚。網(wǎng)上有個說法三流架構(gòu)師照著別人的圖畫架構(gòu)圖二流架構(gòu)師照著自己的代碼畫架構(gòu)圖一流架構(gòu)師讓架構(gòu)圖帶著代碼演進。這話雖然帶點調(diào)侃但點破了一個真相——架構(gòu)圖重構(gòu)這件事的難點從來不在“畫”而在“想”。本文不講虛的直接說清楚架構(gòu)圖重構(gòu)的目標、準備工作、C4分層畫法、一個真實項目的實操記錄以及圖怎么維護才不變成墻紙。1. 為什么要重構(gòu)架構(gòu)圖從“會畫”到“有用”1.1 架構(gòu)圖不是一張圖是一段思考過程很多同學(xué)把架構(gòu)圖當成“交付物”畫完發(fā)給領(lǐng)導(dǎo)、貼進文檔就完事了。這是最大的誤區(qū)。架構(gòu)圖本質(zhì)上是一段思考過程的快照你對系統(tǒng)邊界的判斷、對依賴方向的取舍、對模塊歸屬的定義全部凝固在圖上的方框和箭頭里。重構(gòu)架構(gòu)圖就是把這些判斷重新翻出來審視一遍。系統(tǒng)的業(yè)務(wù)在變、團隊在變、技術(shù)棧在變舊圖上那些“當初合理”的邊界和依賴現(xiàn)在可能早就變形了。比如最早把用戶模塊和訂單模塊畫在一個方框里因為當時訂單邏輯簡單后來訂單邏輯膨脹成十幾個類、三張表還是放在同一個方框里結(jié)構(gòu)上就出問題了。畫布上的第一筆就是逼自己回答一個問題當前這個系統(tǒng)的現(xiàn)實結(jié)構(gòu)和我認為的結(jié)構(gòu)差距在哪里所以重構(gòu)架構(gòu)圖的第一步不是打開畫圖工具而是進入“審視模式”。把系統(tǒng)當成一個陌生項目去讀不帶原有的心理預(yù)設(shè)。這個過程通常很不好受因為你會發(fā)現(xiàn)自己之前引以為傲的設(shè)計在真實代碼面前漏洞百出。但這是架構(gòu)師覺醒的必經(jīng)之路。1.2 舊架構(gòu)圖的四宗罪我經(jīng)手過不少遺留系統(tǒng)它們的架構(gòu)圖幾乎逃不出四個問題第一宗罪是“大泥球”。所有模塊畫在一個大框里框內(nèi)密密麻麻塞了幾十個方塊看不出邊界。這種圖的信息量約等于零因為它沒有表達任何結(jié)構(gòu)。第二宗罪是“顏色地獄”。用紅橙黃綠青藍紫區(qū)分模塊圖例占半頁你把顏色對應(yīng)到方塊上要數(shù)半天。顏色作為輔助編碼可以但不能作為主要表達手段。第三宗罪是“節(jié)日賀卡圖”。比例失調(diào)、箭頭穿透方框、文字斜得扭脖子美觀有余但信息混亂像過節(jié)群發(fā)的賀卡沒人愿意細看。第四宗罪是“孤島圖”。畫完就歸檔代碼演進六個月后圖徹底失真。新同事看這張圖反而被誤導(dǎo)。這類圖比沒有圖更危險。重構(gòu)的目標就是把這四類圖變成“演進圖”邊界清晰、依賴有向、層級分明、隨代碼更新。我不追求一次畫到完美先求得一個“能支撐拆解決策”的可信版本。1.3 重構(gòu)架構(gòu)圖的三個真實收益有人問重構(gòu)架構(gòu)圖到底能帶來什么實際好處我的歸納是三個決策有依據(jù)、團隊有共識、演進有基線。決策有依據(jù)說的是拆分微服務(wù)、模塊合并、中間件選型這類事不用再看代碼猜了。圖上箭頭指向一目了然誰依賴誰、誰是底層支撐、哪塊被三個模塊引用、哪塊像掛在系統(tǒng)上的寄生藤直接呈現(xiàn)在眼前。團隊有共識說的是產(chǎn)品和后端、前端和后端、新人和老人開會時終于能盯著一張圖說事。大家看到的是同一個邊界而不是各自腦補的系統(tǒng)。這張圖就是團隊對系統(tǒng)的“共同基線”。演進有基線說的是每次重構(gòu)動刀前后都把架構(gòu)圖當作對照底稿。改完一處圖跟著動一筆圖上的依賴變少重構(gòu)才真正落地。圖不是目標的終點而是過程中一把隨時拿來量一量的尺子。2. 畫之前要做的事現(xiàn)狀梳理與邊界定義2.1 先收集事實而不是先開畫架構(gòu)圖重構(gòu)最忌諱一上來就畫。你得先回答“現(xiàn)在的系統(tǒng)到底是什么樣”這個客觀問題。我一般從四份素材里找事實代碼倉庫的目錄結(jié)構(gòu)。看包名、模塊名、服務(wù)名這些名字是最誠實的告白。一個叫order-api的模塊依賴一個叫common-utils的模塊那它們的關(guān)系就寫在文件名里。接口與消息隊列清單。Controller 路由、RPC 接口、MQ Topic把每一組“誰調(diào)用誰”記錄下來這就是箭頭的來源。我習慣用一段簡單的腳本掃出所有 Feign Client 接口名和 RabbitListener 指定的隊列名生成資源清單。數(shù)據(jù)庫的庫表歸屬??疵總€服務(wù)是否獨占自己的庫表還是多個服務(wù)共用一個庫這直接反映服務(wù)邊界的真實情況。共用庫表幾乎總是邊界模糊的信號。部署與配置清單??淳€上到底部署了幾個進程、幾個節(jié)點、哪些服務(wù)通過配置中心互相引用地址這能暴露代碼里看不到的運行時依賴。這一步的產(chǎn)出是一張“現(xiàn)狀資源清單”可以用表格記錄調(diào)用方、被調(diào)方、調(diào)用方式HTTP/RPC/MQ/共享DB、調(diào)用頻率猜測。有了這張表后面的圖才有事實支撐。2.2 明確圖的服務(wù)對象和圖幅很多架構(gòu)圖失敗是因為連“給誰看”都沒想清楚。給CTO匯報的架構(gòu)圖和給新人講解代碼的架構(gòu)圖內(nèi)容完全不同。我在動筆前會問自己三個問題第一讀者是誰如果是技術(shù)決策層關(guān)心的是服務(wù)邊界、依賴關(guān)系和技術(shù)選型合理性如果是開發(fā)團隊關(guān)心的是模塊歸屬、接口流向和部署形態(tài)如果是運維關(guān)心的是進程、端口、數(shù)據(jù)存儲位置。第二這幅圖做什么用支撐拆分方案評審解釋線上故障的依賴鏈路還是幫助新人定位修改位置用途不同圖的顆粒度完全不同。第三圖幅有多大一張圖裝不下整個世界。系統(tǒng)上下文、服務(wù)容器、模塊組件、代碼類這四層信息放在四張圖里而不是揉在一張巨圖里。我見過太多失敗案例都是想“一圖全覽”結(jié)果任何一層都沒看清。2.3 工具選型找個能進版本庫的畫布工具這塊我這些年基本形成了一個原則能文本化、能進Git、能自動生成優(yōu)先級最高。因為架構(gòu)圖是要隨代碼演進的二進制圖形文件在合并沖突、歷史追溯方面實在很難用而文本繪圖可以 diff、可以 code review。個人常用的四類工具各有利弊下面這個表可以直接參考工具優(yōu)點缺點適合場景PlantUML文本作圖、支持C4宏、版本友好、免費布局自動生成復(fù)雜圖偶爾錯位C4四層圖、時序圖、部署圖Mermaid渲染輕量、GitHub原生支持、上手快表達復(fù)雜依賴時略顯吃力快速示意圖、文檔內(nèi)嵌圖draw.io所見即所得、模板豐富二進制文件難diff協(xié)作靠手動一次性對外匯報圖、非技術(shù)場景Excalidraw手繪風、適合白板討論不易沉淀為長期維護物頭腦風暴、快速建模推薦組合是日常架構(gòu)決策用 PlantUML 的 C4 模板畫完順手生成圖片放入文檔對外匯報用 draw.io 做美化版團隊白板討論用 Excalidraw。三種工具服務(wù)不同場合核心模型只在 PlantUML 里維護避免多處維護不一致。3. 核心方法C4模型下的一筆一畫3.1 Level 1 系統(tǒng)上下文圖先畫外部世界C4 模型把架構(gòu)圖分為四個層次上下文、容器、組件、代碼。架構(gòu)圖重構(gòu)的“第一筆”應(yīng)該從 Level 1 系統(tǒng)上下文圖開始。系統(tǒng)上下文圖的主角是“這個系統(tǒng)本身”和“它周圍的人”。人包括用戶角色、外部系統(tǒng)、第三方服務(wù)。這張圖不畫內(nèi)部結(jié)構(gòu)只畫邊界系統(tǒng)對外提供什么依賴外部的什么。它回答的問題是我們的系統(tǒng)在更大的生態(tài)里處在什么位置。畫這一層最大的價值在于邊界意識的建立。很多重構(gòu)的坑“坑”在沒搞清楚系統(tǒng)的外部依賴和真實用戶就動手了。比如一個訂單系統(tǒng)真正的用戶不只是 C 端消費者還有后臺運營、客服系統(tǒng)、供應(yīng)鏈系統(tǒng)、財務(wù)系統(tǒng)。漏掉一個外部依賴架構(gòu)圖就不完整拆解方案就可能在后續(xù)被某個“隱藏用戶”打亂。3.2 Level 2 容器圖把系統(tǒng)拆成可部署單元Level 2 容器圖里“容器”指的是可獨立部署/運行的單元微服務(wù)、Web應(yīng)用、后臺任務(wù)、數(shù)據(jù)庫、消息隊列等。這一層是微服務(wù)架構(gòu)圖的主角也是多數(shù)人最熟悉的“微服務(wù)架構(gòu)圖”的樣子。畫這一層的核心動作是決定哪些功能屬于同一個容器哪些必須拆出去。判定依據(jù)通常有三條獨立生命周期、獨立伸縮需求、獨立故障邊界。如果一個模塊的發(fā)布頻率明顯高于其他模塊且它崩了不影響核心鏈路就有充分的理由獨立成容器。這層圖上的箭頭含義必須統(tǒng)一。我用一種約定實線箭頭表示同步調(diào)用HTTP/RPC虛線箭頭表示異步消息MQ細線雙向表示共享數(shù)據(jù)庫訪問但方向弱化。箭頭上標注接口名或 Topic 名不標沒有意義。很多圖畫了大量箭頭但讀者不知道這些線是什么含義圖就白畫了。3.3 Level 3 組件圖打開容器看零件Level 3 組件圖針對某一個具體容器畫出內(nèi)部的“零件”哪些類/模塊負責接口、哪些負責業(yè)務(wù)規(guī)則、哪些負責數(shù)據(jù)訪問以及它們之間的關(guān)系。這層圖不是給所有人看的是給要動這個容器的開發(fā)團隊看的。畫這一層時我堅持“一個容器一張組件圖寧缺毋濫”。只有這個容器需要重構(gòu)、需要被仔細拆解時才畫它的組件圖。至于底層代碼實現(xiàn)細節(jié)交給代碼注釋和單元測試架構(gòu)圖上不堆砌類名。在組件圖里最容易發(fā)現(xiàn)的就是“假容器、真泥球”。表面上看這是一個獨立的訂單服務(wù)打開組件圖才發(fā)現(xiàn)里面塞了庫存的緩存預(yù)扣、支付的回調(diào)處理、營銷活動的優(yōu)惠計算邊界糾纏不清。組件圖的意義就是揭開這層遮羞布。3.4 避坑依賴方向與邊界劃法架構(gòu)圖重構(gòu)中箭頭方向最容易畫錯而方向恰恰是最有價值的信息。我的約定是依賴被依賴方箭頭從依賴方指向被依賴方。不能在圖中一會兒“誰調(diào)誰”一會兒“誰被誰調(diào)用”混用箭頭語義會讓整張圖的推理作用歸零。依賴方向的判定有個簡便標準誰發(fā)生變更會影響對方A 改了導(dǎo)致 B 要跟著改就是 B 依賴 A箭頭從 B 指向 A。這比看運行時調(diào)用的代碼更容易判斷因為它在評估“影響范圍”而非僅僅觀察“調(diào)用行為”。邊界劃法上一個核心原則是“邊界要劃在變更頻率不一致的地方”。訂單模塊和支付模塊如果一周變更十幾次一把梭放在一起每次發(fā)布都互相牽連那它們之間就是一條應(yīng)該畫出來的邊界。相反兩個技術(shù)組件雖然代碼上是兩個模塊但如果它們總是一起變更、一起發(fā)布、部署在同一進程里畫圖時也可以先作為一個容器對待。4. 實操記錄一個微服務(wù)系統(tǒng)的架構(gòu)圖重構(gòu)4.1 重構(gòu)前的原始狀態(tài)上季度接手了一個典型的業(yè)務(wù)系統(tǒng)姑且叫它“訂單中臺”。代碼倉庫里有一份半年前的架構(gòu)圖畫的是五個服務(wù)網(wǎng)關(guān)、用戶、訂單、商品、支付??催@張圖一切井井有條。但真正接入手后發(fā)現(xiàn)完全不是那么回事支付服務(wù)的代碼里直接訪問了用戶服務(wù)的數(shù)據(jù)庫表。嚴格說它倆是“共享庫”但圖上是虛線松耦合表示異步調(diào)用。訂單服務(wù)里塞了一個“營銷計算器”的模塊它既讀商品服務(wù)的價格表又通過 Feign 調(diào)營銷服務(wù)獲取券信息。論運行功能它散落人間。網(wǎng)關(guān)服務(wù)的過濾器鏈里藏了一段日志上報邏輯直接往外部日志平臺發(fā)數(shù)據(jù)繞過了所有內(nèi)部服務(wù)。如果用舊圖去指導(dǎo)拆分只會按圖索驥把本來糾纏的東西自然保留。這張圖給出的邊界是虛假的邊界。4.2 分步處理理清單、畫事實、找病灶我第一步做的事情是把統(tǒng)計到的接口調(diào)用和庫表歸屬做成了現(xiàn)狀資源表并且把舊架構(gòu)圖丟到一邊基于代碼事實畫了一張“現(xiàn)狀態(tài)圖”?,F(xiàn)狀態(tài)圖不追求美觀只有方塊和箭頭甚至故意畫得亂一點。畫的過程中出現(xiàn)了幾個關(guān)鍵發(fā)現(xiàn)訂單服務(wù)到用戶數(shù)據(jù)庫的訪問路徑畫出來就是一條“越界大動脈”。這一步直接暴露了共享庫問題也決定了后面拆分時“用戶庫必須先獨立、支付服務(wù)必須改走接口”的處理順序。營銷計算器被三個服務(wù)引用畫出來像個“中心樞紐”但它不屬于任何一個基礎(chǔ)設(shè)施層而是混雜在訂單模塊里的業(yè)務(wù)組件。這說明營銷能力該單獨沉淀成服務(wù)或者明確下沉為公共模塊。網(wǎng)關(guān)過濾器里的日志邏輯畫出來發(fā)現(xiàn)網(wǎng)關(guān)與外部日志平臺之間存在一條數(shù)據(jù)通路這在架構(gòu)上沒有統(tǒng)一出口。這里的處理不是立刻重寫而是先明確“統(tǒng)一接入日志服務(wù)”的新目標。4.3 重構(gòu)后的圖形結(jié)構(gòu)在現(xiàn)狀態(tài)圖基礎(chǔ)上我和團隊定下了目標架構(gòu)圖。對比一下重構(gòu)前后的結(jié)構(gòu)差異重構(gòu)前依賴關(guān)系呈“網(wǎng)狀發(fā)散”隨便拉兩個服務(wù)之間都有線沒有人能在腦海里展開這張圖。重構(gòu)后依賴關(guān)系是分層的上層業(yè)務(wù)流訂單、營銷、商品依賴中層領(lǐng)域服務(wù)用戶、支付、庫存中層又依賴底層基礎(chǔ)設(shè)施配置中心、日志平臺、網(wǎng)關(guān)路由。每條依賴箭頭都清晰指向一個方向。邊界上的變化也很大。用戶數(shù)據(jù)訪問權(quán)限收口到用戶服務(wù)外部一律通過接口獲取用戶信息。營銷計算器從訂單服務(wù)中遷出沉淀為獨立的營銷能力服務(wù)同時掛到中臺的能力開放層。網(wǎng)關(guān)里的日志邏輯剝離統(tǒng)一收集到日志服務(wù)處理。這版圖不是一天畫出來的中間過了三輪評審每輪都會發(fā)現(xiàn)“舊人情結(jié)”在作祟。有人覺得“支付讀一下用戶庫也沒啥省事”這種觀點必須被圖上那條越界箭頭和政策決定壓過。圖是我們的共同基線不是哪個人說省事就能繞過的。4.4 用架構(gòu)圖反推并發(fā)現(xiàn)問題架構(gòu)圖不只是結(jié)果我還是把它當排查工具來用。圖上每一處“環(huán)形依賴”幾乎都對應(yīng)著一處真實的代碼異味。比如在現(xiàn)狀態(tài)圖里訂單服務(wù)調(diào)營銷服務(wù)營銷服務(wù)又回調(diào)訂單服務(wù)查訂單狀態(tài)形成一個小環(huán)。這種環(huán)形依賴在運行時不一定會出錯但它意味著兩個團隊無法獨立發(fā)布——任何一方的改動都可能波及另一方。看到這個環(huán)對應(yīng)的動作就是定下一個決策營銷服務(wù)查詢訂單狀態(tài)必須改成讀訂閱的訂單事件或者查詢只讀視圖絕不允許反向調(diào)用線上接口。再比如“明星依賴”問題。用戶服務(wù)被幾乎所有服務(wù)依賴圖上一看五六個箭頭都指向它。這個節(jié)點一抖動全站雪崩。架構(gòu)圖上這種“明星”節(jié)點一旦出現(xiàn)就要考慮加緩存、加降級、物理隔離或者在能力開放層加一層適配。沒有圖的時候這些問題分散在告警系統(tǒng)里每次都像在打地鼠。另一點要提醒架構(gòu)圖重構(gòu)過程中不是所有問題都要當場解決。我們的原則是“看見、記錄、排期”。圖上標出來列入技術(shù)債清單設(shè)定處理優(yōu)先級比當場修更重要。重構(gòu)的目標是把結(jié)構(gòu)畫清楚不是順手把系統(tǒng)改完一步步來才不會失控。5. 常見問題速查與長效維護5.1 架構(gòu)圖維護的六個高頻坑維護架構(gòu)圖這事踩坑的人很多我整理成了一張速查表看一眼就知道怎么處理問題現(xiàn)象根因處理方式圖上沒有分層全部平鋪沒想清楚讀者是誰按C4分層一個人一張圖只看一層箭頭滿天飛但無標注依賴語義混用統(tǒng)一箭頭含義標注接口名或事件名圖例比圖還長顏色表示過度顏色只用于輔助區(qū)分不承載核心信息新舊混畫圖里一半代碼一半概念層級跳變明確每張圖的顆粒度不混層畫完三個月沒更新缺少演進制度把架構(gòu)圖納入代碼評審前置門檻一張圖上畫滿50個模塊貪大求全堅持一張圖一個主題必要時畫多張細看這些坑根子都在一條圖沒有和“決策”綁定。如果一個圖不服務(wù)任何決策就沒人有動力維護它。5.2 讓架構(gòu)圖和代碼同步演進架構(gòu)圖和代碼同步這是維護的核心。我見過不少團隊把“架構(gòu)圖更新”當成一個年底任務(wù)結(jié)果每次都是年底花一周重畫一次平時沒人管。要想真正同步就得把“更新架構(gòu)圖”這個動作嵌入到日常開發(fā)的流程里。我實踐下來比較有效的一個動作是在 MRMerge Request模板里增加一個勾選項——“本次變更是否涉及架構(gòu)圖所示的服務(wù)/模塊邊界如果是請同步更新架構(gòu)圖并附帶截圖”。這個勾選項逼著開發(fā)者在提交代碼時思考自己的變更落在哪條邊界上。另一個動作是“架構(gòu)評審作為發(fā)布前置條件”。凡是涉及新增服務(wù)、新增對外接口、新增共享庫訪問的變更強制走一次架構(gòu)圖對照評審。評審不通過不能合入主分支。這個制度一開始會被開發(fā)團隊嫌棄覺得“畫個圖還要審批”但堅持兩三個月所有人都會認可它帶來的確定性——沒有人在合代碼的時候才突然悟出“這個模塊原來不該放這里”。5.3 架構(gòu)決策記錄與圖互相印證長期維護架構(gòu)圖光有圖還是不夠。我建議你從重構(gòu)的第一天起就開始同步維護一份 ADRArchitecture Decision Record架構(gòu)決策記錄。每做一個重要邊界決策比如“支付服務(wù)獨立訪問用戶接口”就寫一條輕量記錄背景、決策、影響、替代方案。架構(gòu)圖和 ADR 互相印證。圖表達“最終結(jié)果”ADR 表達“為什么是這么定”。新人接手的時候看圖是“What”讀 ADR 是“Why”。這份組合才是完整的架構(gòu)知識沉淀。ADR 怎么寫才不勸退我自己的模板就四段背景一句話、約束有哪些限制、決策定了什么、后果帶來的好處和代價。寫一頁以內(nèi)控制在 10 分鐘能完成。時間拖長了堅持不住。這樣堅持一年團隊就擁有了一本活的“架構(gòu)演進史”。提示系統(tǒng)架構(gòu)師考試近年來也很看重“分層”和“邊界分析”這類能力考綱中架構(gòu)設(shè)計部分反復(fù)強調(diào)從邏輯架構(gòu)、物理架構(gòu)、運行架構(gòu)等不同視圖描述系統(tǒng)。這個 C4 分層習慣對備考同樣有效畫圖時養(yǎng)成分視角建模的肌肉記憶比考前突擊背概念來得扎實。6. 從畫布到引領(lǐng)架構(gòu)圖如何驅(qū)動團隊6.1 靜態(tài)圖之外也要會看動態(tài)圖架構(gòu)圖重構(gòu)到一定程度你會發(fā)現(xiàn)靜態(tài)圖只表達“結(jié)構(gòu)的截面”而系統(tǒng)真正的復(fù)雜度往往體現(xiàn)在“運行時的動態(tài)交互”上。接口的時序、故障的擴散、數(shù)據(jù)的流轉(zhuǎn)這些信息靜態(tài)圖表達不了。我的處理方式是不強行把動態(tài)信息塞進架構(gòu)圖而是用“架構(gòu)圖時序圖”組合。架構(gòu)圖負責規(guī)劃邊界時序圖負責描述關(guān)鍵路徑的交互流程。畫關(guān)鍵業(yè)務(wù)鏈路的時序圖時腦海里要有架構(gòu)圖的坐標系時刻知道正在畫的這條交互序列落在哪條服務(wù)邊界上。對架構(gòu)師來說靜態(tài)圖是骨架動態(tài)圖是行為。兩者配合才能在評審別人方案時直接指出“你這個交互流程跨了三個服務(wù)邊界失敗處理的歸屬沒有寫清楚”之類的問題。6.2 用架構(gòu)圖做技術(shù)評審和技術(shù)決策技術(shù)評審會議最怕沒有共同語境后端說這個接口要加到訂單服務(wù)前端說為什么訂單服務(wù)又要加一個通知方法產(chǎn)品說這不是我們當初說的模塊劃分。有了架構(gòu)圖評審會就變成了對著圖上的方塊和箭頭討論問題。評審時我常用的三連問這個變更落在圖上哪個方塊里它和相鄰方塊的關(guān)系是加箭頭還是改箭頭改動后是否會形成新的環(huán)或新的明星節(jié)點這三連問看起來簡單但在架構(gòu)評審里效果很好能把討論話題從“怎么實現(xiàn)”拉回“邊界怎么劃”讓技術(shù)方案從一開始就走在正確的架構(gòu)方向。畫圖還有一個不容易察覺的作用它是架構(gòu)師建立“可信度”的工具。你拿著代碼里挖出來的真實依賴關(guān)系圖去談拆分和你拍著胸脯說“我覺得這里該拆”力度完全不同。圖是思考的外化這是“畫布上的第一筆”真正的分量。6.3 從“畫圖的人”到“引導(dǎo)的人”回到開頭那個說法三流架構(gòu)師畫圖一流架構(gòu)師引領(lǐng)。但“引領(lǐng)”不是脫離架構(gòu)圖、站在高處指手畫腳。我的理解恰恰相反引領(lǐng)的前提是你比團隊所有人更熟悉這張圖上每一條邊的來歷和后果。你不是在畫圖你是在為團隊建立一套認知系統(tǒng)的坐標系。這個坐標系一旦建立后續(xù)的每一次重構(gòu)、每一次容量評估、每一次故障排查都掛在這個坐標系上。架構(gòu)師從“被技術(shù)債追著跑”的狀態(tài)變成了“帶著團隊看清結(jié)構(gòu)再動手”的狀態(tài)。這就是“從重構(gòu)到引領(lǐng)”的真正起點。經(jīng)歷了這次架構(gòu)圖重構(gòu)我最大的體會是重構(gòu)掉的不只是圖上那些混亂的線條更是自己心里對系統(tǒng)的模糊感覺。第一筆落下去的時候你就已經(jīng)回不了頭——因為你開始相信任何一團亂麻都能理出結(jié)構(gòu)任何一張模糊的圖都能被畫清晰。最后一招想分享給卡在“不知道從哪里開始”的朋友挑一個你手頭最痛的系統(tǒng)不要畫宏大圖只畫一張 Level 1 系統(tǒng)上下文圖加一張 Level 2 容器圖把“現(xiàn)狀”如實畫出來就行不用美化。畫完你會發(fā)現(xiàn)問題不是不知道怎么辦而是從來沒有把問題看完整過。