圖表設(shè)計(jì):從需求拆解到可維護(hù)架構(gòu)圖)
圖表這件事說難不難說容易也容易翻車。我見過太多技術(shù)方案里堂堂一個(gè)核心鏈路圖畫完沒人看得懂也見過明明邏輯很清楚的一個(gè)流程因?yàn)楣?jié)點(diǎn)堆得太滿評審時(shí)被反復(fù)追問。后來我把一套叫“diagram-design”的思路沉淀下來專門用來處理架構(gòu)圖、流程圖、數(shù)據(jù)流轉(zhuǎn)圖這一類技術(shù)圖表的從零設(shè)計(jì)。它不是什么高深理論就是一套從拆需求、選工具、定布局到落文檔的可復(fù)用方法適合經(jīng)常寫技術(shù)方案、維護(hù)知識(shí)庫、或者在團(tuán)隊(duì)里負(fù)責(zé)文檔建設(shè)的人參考。這篇文章把整套流程和踩過的坑一起展開希望能幫你少走點(diǎn)彎路。1. 先別急著開畫想清楚這張圖到底要表達(dá)什么很多圖之所以畫出來沒人看根本原因不是畫得不好看而是畫之前沒想清楚“給誰看、在什么場景看、看完要得到什么結(jié)論”。diagram-design 的第一步不是打開工具而是先回答這三個(gè)問題。1.1 圖表先回答三連問讀者是誰、場景是什么、結(jié)論是什么我最早畫圖是典型的學(xué)生思維恨不得把系統(tǒng)里所有模塊、所有接口、所有依賴關(guān)系全部塞進(jìn)一張圖里覺得這樣才叫“完整”。結(jié)果圖一拉出來橫向超過顯示器兩倍縱向滾兩屏每個(gè)節(jié)點(diǎn)旁邊還有三條注解線。我自己都看不清更別說別人。后來我給自己定了一個(gè)死規(guī)矩落筆之前先寫三句話。第一句寫給誰看比如“給后端同事看”和“給產(chǎn)品經(jīng)理看”完全不是一回事。第二句在什么場景看是評審會(huì)上的演示稿還是文檔里冷讀的資料。第三句看完要得出什么結(jié)論比如“這個(gè)服務(wù)的調(diào)用鏈路上存在一個(gè)單點(diǎn)需要冗余”或者是“狀態(tài)機(jī)的流轉(zhuǎn)是合法的不存在死循環(huán)”。這三句話寫不出來寧可先不開畫。這三連問直接決定了圖的抽象層級和省略范圍。如果是給非技術(shù)同事看就不該出現(xiàn)數(shù)據(jù)庫連接池、線程數(shù)、緩存命中率這些細(xì)節(jié)如果是給運(yùn)維同學(xué)看業(yè)務(wù)含義反而可以弱化重點(diǎn)是端口、協(xié)議、部署拓?fù)洹_@里有一條經(jīng)驗(yàn)一張圖只解決一個(gè)問題。我發(fā)現(xiàn)很多圖難懂是因?yàn)樽髡呦氚选跋到y(tǒng)長什么樣”和“請求怎么走”以及“異常怎么處理”一次性表達(dá)出來結(jié)果三種問題互相干擾。實(shí)際上應(yīng)該拆成部署結(jié)構(gòu)圖、邏輯架構(gòu)圖、時(shí)序交互圖、異常流程圖這幾張每張圖都只回答一個(gè)問題。這樣組合起來雖然要多花一點(diǎn)時(shí)間但讀者體驗(yàn)是完全不同的。1.2 分層拆解別讓一圖背負(fù)所有復(fù)雜度我會(huì)把一個(gè)待展示的系統(tǒng)先在腦子里拆成三層邊界層、能力層、鏈路層。邊界層回答系統(tǒng)與外部世界的交互畫出用戶入口、外部依賴、消息隊(duì)列對端、下游服務(wù)。能力層回答系統(tǒng)內(nèi)部有哪些核心模塊或子域各自職責(zé)是什么。鏈路層則選擇一條具體業(yè)務(wù)場景畫出請求或數(shù)據(jù)經(jīng)過哪些模塊、每個(gè)步驟做了什么。拆完之后你會(huì)發(fā)現(xiàn)大多數(shù)情況下根本不需要把這三層畫在一張圖里。高層文檔適合放邊界層加能力層重點(diǎn)講清楚職責(zé)邊界。技術(shù)評審或排障文檔才需要鏈路層而且鏈路層通常只畫一條主線其他分支用“省略號”或者“詳見另一張圖”的方式帶過。舉個(gè)例子某內(nèi)部通知系統(tǒng)的整理過程。第一次信息采集時(shí)我把短信、郵件、站內(nèi)信、Push、管理后臺(tái)、渠道供應(yīng)商、重試隊(duì)列、黑名單服務(wù)這些東西全部列了一遍。如果全畫在一張圖里至少有三十個(gè)節(jié)點(diǎn)和五十條連線根本沒法看。拆解后就變成了三張第一張是通知系統(tǒng)與外部系統(tǒng)的邊界圖只有六個(gè)節(jié)點(diǎn)第二張是系統(tǒng)內(nèi)部模塊圖約十個(gè)節(jié)點(diǎn)第三張是“發(fā)送一條短信失敗后如何重試”的鏈路圖只有五個(gè)節(jié)點(diǎn)。三張圖都清晰組合在一起又完整評審時(shí)大家各取所需不會(huì)再有人對著圖發(fā)懵。這件事想表達(dá)的其實(shí)是diagram-design 核心能力之一就是做減法。把復(fù)雜系統(tǒng)拆成多個(gè)單一語義的視圖而不是用一張“巨型全圖”來證明你畫圖很努力。2. 工具選型文本優(yōu)先還是畫布優(yōu)先各有各的命工具選擇是圖表設(shè)計(jì)里最容易被低估的一環(huán)。很多人直接打開一個(gè)順手的繪圖工具就開始拖節(jié)點(diǎn)結(jié)果到了維護(hù)階段才痛苦。圖表也是要維護(hù)的而且圖表過期比文檔過期更坑人——因?yàn)樗雌饋砗苷酱蠹視?huì)下意識(shí)當(dāng)真。選工具時(shí)核心要回答的是這張圖的源文件要放在哪、誰能改、改完怎么評審。2.1 文本生成派適合進(jìn)代碼庫、可diff、可批量改文本類繪圖工具天生的優(yōu)勢是可以把圖“寫”出來。節(jié)點(diǎn)和連線都以純文本形式存在放進(jìn)代碼倉庫之后可以做版本管理、做diff、做review。有人改了一個(gè)節(jié)點(diǎn)另一個(gè)人能清楚地看到這一版和上一版哪變了。這是一個(gè)聽起來普通、實(shí)際影響巨大的特性。團(tuán)隊(duì)協(xié)作中最怕的就是某天有人用畫圖軟件更新了一張?jiān)O(shè)計(jì)圖別人完全不知道哪里變了只能瞪著兩張大圖眼對眼。文本方案的另一個(gè)優(yōu)勢是批量修改。假設(shè)你定義了模板某個(gè)公共組件在整個(gè)目錄的多張圖里都有出現(xiàn)現(xiàn)在需要改這個(gè)組件的名字或顏色。如果是拖拽工具你要打開每一個(gè)文件手動(dòng)選節(jié)點(diǎn)改樣式保存。文本工具則只要做一次模式替換重新生成全目錄圖表一次更新完。這種情況在架構(gòu)演進(jìn)期特別常見一個(gè)月里組件被改名三四次都是正常的。文本派也有明顯的短板布局可控性弱。如果圖比較復(fù)雜自動(dòng)布局出來的箭頭交叉、標(biāo)簽重疊時(shí)常發(fā)生。尤其是領(lǐng)導(dǎo)臨時(shí)讓你“把這兩個(gè)模塊放得近一點(diǎn)”時(shí)拖拽工具里兩秒鐘的事文本工具可能要調(diào)半天順序和分組。所以文本派更適合邏輯關(guān)系清晰、節(jié)點(diǎn)數(shù)量在可控范圍內(nèi)、且需要長期維護(hù)的技術(shù)文檔圖。2.2 拖拽繪圖派適合快速頭腦風(fēng)暴和精細(xì)化排版畫布型工具的強(qiáng)項(xiàng)是自由。你可以隨意擺放節(jié)點(diǎn)、微調(diào)坐標(biāo)、拉取路徑、調(diào)整顏色做到像素級的排版控制。非常適合會(huì)議期間快速把想法視覺化、給非技術(shù)背景的人做高保真示意圖、或者畫那種需要把多個(gè)小圖拼在一起的大圖。在這個(gè)流派里我最常用的工作流是三步先畫出粗糙的方框確定大致排布然后調(diào)整對齊和間距錨點(diǎn)吸附保證連線不會(huì)歪最后統(tǒng)一字號、統(tǒng)一配色導(dǎo)出時(shí)候選高清位圖或矢量格式。需要注意的坑也很多。一是畫布型工具的文件格式往往是私有格式換工具遷移成本很高。二是如果你沒有刻意保存成兼容格式別人即使拿到源文件也可能打不開或打開后排版全亂。三是多人同時(shí)編輯一張畫布圖傳統(tǒng)模式下必然產(chǎn)生沖突改完也不知道改了什么。這不是說畫布型工具不能用而是要讓它的使用場景和文本派區(qū)分開。快速討論、一次性演示、對外高保真圖用它長期維護(hù)、多人協(xié)作、版本敏感的圖用文本派。2.3 混合工作流先用文本理邏輯再進(jìn)畫布調(diào)樣式我現(xiàn)在的習(xí)慣是混合使用。具體分成三個(gè)階段結(jié)構(gòu)階段、樣式階段、發(fā)布階段。結(jié)構(gòu)階段我會(huì)在文本工具里把節(jié)點(diǎn)和連線全部寫出來強(qiáng)制自己用文本語言描述清楚每個(gè)實(shí)體和關(guān)系。這個(gè)階段最忌諱用眼睛去拖因?yàn)橥献?huì)讓人沉浸在“擺放”的滿足感里反而忽略了邏輯上的漏洞。文本階段能逼著你先想清楚A和B是什么關(guān)系是調(diào)用、依賴還是數(shù)據(jù)流方向是什么這些文本能明確表達(dá)。樣式階段再把結(jié)構(gòu)化內(nèi)容導(dǎo)入到畫布工具里做精細(xì)排版。調(diào)整的主要是視覺引導(dǎo)比如把主鏈路擺成一條從左到右的主軸把輔助依賴放在下方把異常分支用虛線與其他線區(qū)分開。發(fā)布階段我會(huì)同時(shí)輸出兩樣?xùn)|西一張高清圖片嵌入文檔以及這份圖的源文件。如果源文件所在路徑能放進(jìn)代碼庫或團(tuán)隊(duì)共享目錄就更好了。圖片負(fù)責(zé)“看”源文件負(fù)責(zé)“改”。很多人只看圖不看源文件等到圖要改的時(shí)候找不到源頭這是維護(hù)事故必須避免。3. 從需求到成品一張架構(gòu)圖的完整實(shí)操過程前面講的是方法和選型這一節(jié)走一遍實(shí)際過程。用我在某跨平臺(tái)系統(tǒng)整理的一次圖表設(shè)計(jì)作為案例從最原始的零散描述開始到最終產(chǎn)出一張可以直接放進(jìn)技術(shù)方案的架構(gòu)圖。3.1 信息收集與結(jié)構(gòu)化從一段“流水賬”拆出節(jié)點(diǎn)和連線原始接到的信息是這樣的“我們的系統(tǒng)接收上游平臺(tái)回傳的數(shù)據(jù)然后進(jìn)MQ消費(fèi)者去處理消息其中有一步要把原始數(shù)據(jù)存一份到對象存儲(chǔ)還可能要調(diào)第三方接口做內(nèi)容審核審核不通過的要進(jìn)人工審核池通過的就正式入庫用戶查詢走另一套查詢服務(wù)?!边@段話本身不能用直接照著畫出來的圖跟菜單一樣沒有重點(diǎn)。先把它拆成節(jié)點(diǎn)和連線。第一輪節(jié)點(diǎn)清單大概是這樣的數(shù)據(jù)源上游平臺(tái)、接入網(wǎng)關(guān)、消息隊(duì)列、消息消費(fèi)者、對象存儲(chǔ)、內(nèi)容審核服務(wù)、人工審核池、業(yè)務(wù)數(shù)據(jù)庫、查詢服務(wù)、用戶端。連線則有數(shù)據(jù)源到網(wǎng)關(guān)、網(wǎng)關(guān)到MQ、MQ到消費(fèi)者、消費(fèi)者到對象存儲(chǔ)、消費(fèi)者到審核服務(wù)、審核服務(wù)到人工池、審核服務(wù)回執(zhí)、消費(fèi)者到業(yè)務(wù)庫、查詢服務(wù)到業(yè)務(wù)庫、用戶端到查詢服務(wù)。到這里信息還不是圖因?yàn)槿鄙賹哟魏头纸M。我接著做分類第一層是外部系統(tǒng)包括數(shù)據(jù)源、審核服務(wù)、用戶端。第二層是接入層包括網(wǎng)關(guān)和MQ。第三層是處理層包括消費(fèi)者、存儲(chǔ)、數(shù)據(jù)庫、審核流程相關(guān)。于是這三個(gè)分組正好對應(yīng)邊界層、能力層、鏈路層的關(guān)系。分完組之后圖的骨架就出來了。操作上我習(xí)慣用一個(gè)簡單的表格來管理這個(gè)信息表頭是節(jié)點(diǎn)名、類型、上游來源、下游去向、備注。備注里寫清楚這條連接代表調(diào)用還是數(shù)據(jù)流以及是否屬于主鏈路、是否屬于異常分支。做表格的過程本質(zhì)上就是預(yù)編譯后面畫圖只是把這個(gè)表格“渲染”出來而已。3.2 布局與視覺規(guī)范主鏈路靠左到右層級靠分組語義靠線型布局是決定一張圖能不能“三秒讀懂”的關(guān)鍵環(huán)節(jié)。我固定的布局原則是主鏈路貫穿從左到右的水平方向盡量少拐彎。支線或輔助流程放在主鏈路下方盡量用直線和直角。異常分支、超時(shí)補(bǔ)償、人工處理這些非主流路徑統(tǒng)一用虛線或不同顏色區(qū)分。豎向上則用分組代表邏輯層級比如外部環(huán)境、接入層、核心處理層、持久化層由上而下一目了然。有人會(huì)問為什么不是從右到左或者從下到上因?yàn)槿说囊曈X閱讀習(xí)慣大體上是從左到右、從上到下。圖表設(shè)計(jì)不是藝術(shù)創(chuàng)作它要降低認(rèn)知負(fù)擔(dān)。遵循閱讀習(xí)慣就是讓注意力自然落在主流程上不需要讀者額外去猜起點(diǎn)在哪。配色方面也要定規(guī)矩避免把一張圖搞得像調(diào)色盤。我通常只用五種顏色主流程節(jié)點(diǎn)用一種中性色外部依賴用一種統(tǒng)一的基礎(chǔ)色數(shù)據(jù)存儲(chǔ)用一種偏冷的色異常分支節(jié)點(diǎn)用一種低飽和的警示色輔助說明文字用灰色。這里的關(guān)鍵是顏色代表“語義”不是代表“我喜歡”。如果某一天有人打開圖發(fā)現(xiàn)某個(gè)模塊換了個(gè)新顏色那么新顏色必須有明確含義否則就不許換。這一條能讓團(tuán)隊(duì)維護(hù)時(shí)的溝通成本大大降低。命名是另一個(gè)容易忽略的點(diǎn)。節(jié)點(diǎn)文本建議統(tǒng)一采用“動(dòng)詞短語”或“名詞短語”的其中一種不要混著來。比如同一個(gè)圖層里“訂單處理”是名詞描述“校驗(yàn)用戶權(quán)限”是動(dòng)詞描述。實(shí)際上我更推薦用動(dòng)詞短語標(biāo)注動(dòng)作節(jié)點(diǎn)用名詞短語標(biāo)注實(shí)體節(jié)點(diǎn)。順序上盡量從“讀取方”指向“提供方”或者從“調(diào)用方”指向“被調(diào)用方”方向一旦統(tǒng)一看圖的人就不會(huì)產(chǎn)生歧義。3.3 終稿檢查清單導(dǎo)出前的最后一輪自檢圖基本畫完后我還留著最后一輪檢查專門抓那些一眼能看出來的低級但致命的錯(cuò)誤。這個(gè)清單基本是固定的所有線都有明確的起點(diǎn)和終點(diǎn)不存在懸空線。每個(gè)節(jié)點(diǎn)的措辭保持統(tǒng)一粒度不要出現(xiàn)“用戶登錄”和“調(diào)用用戶中心接口獲取用戶基本信息”這種粒度不一致的并列節(jié)點(diǎn)。主鏈路是否在三秒內(nèi)能被識(shí)別出來如果不能說明布局有問題。有沒有交叉線超過兩處如果有考慮是否換主軸方向或者調(diào)整節(jié)點(diǎn)順序。標(biāo)簽是否完整比如“同步接口”“異步消息”“依賴外部服務(wù)”這些重要語義是否在圖上直接可讀而不是需要看底下的圖例去猜。導(dǎo)出圖片的清晰度是否足夠直接放縮到200%預(yù)覽檢查邊緣是否有鋸齒。源文件是否已保存并被引用文檔里的注釋或圖下說明是否寫了這張圖表達(dá)的核心結(jié)論。這套檢查清單看起來很瑣碎但對應(yīng)到評審會(huì)上都是被血淚教訓(xùn)過的。尤其是第一和第三項(xiàng)只要懸空線存在或者主鏈路不清晰評審一開始就會(huì)被人從圖上發(fā)現(xiàn)漏洞然后整個(gè)方案的說服力都會(huì)打折。4. 典型踩坑與排查記錄最后整理一下我在圖表設(shè)計(jì)這件事上實(shí)際遇到過的幾個(gè)高頻問題以及排查思路和處理方案。這一節(jié)更像一個(gè)個(gè)人備忘希望能幫你省掉一些調(diào)試時(shí)間。4.1 文字重疊與圖片發(fā)虛問題多半在布局而非渲染文字重疊通常不是工具bug而是節(jié)點(diǎn)大小和內(nèi)容長度不匹配。我在文本派工具里遇到最多。解決辦法是在設(shè)計(jì)階段就給節(jié)點(diǎn)指定統(tǒng)一的文本寬度預(yù)算比如主名最長八個(gè)字備注最長十二個(gè)字。字?jǐn)?shù)超了就換行或縮寫而不是放任節(jié)點(diǎn)自動(dòng)撐大。這一招的好處在畫布型工具里也能復(fù)刻先統(tǒng)一設(shè)置節(jié)點(diǎn)的最小寬度再排版畫面干凈很多。另一類是導(dǎo)出圖片發(fā)虛。常見原因是默認(rèn)導(dǎo)出的位圖分辨率不夠。建議導(dǎo)出時(shí)指定一個(gè)截圖尺寸放大倍數(shù)比如至少兩倍或三倍確保嵌入文檔后即使再放大也不會(huì)糊。如果工具支持矢量導(dǎo)出就直接導(dǎo)矢量格式再放到文檔里拉高放大倍率也不怕。切記不要在文檔里直接貼工具內(nèi)的截圖小圖這種圖的觀感會(huì)瞬間拉低整篇文檔的專業(yè)度。4.2 箭頭交叉與圖過長可以用“聚合”緩解圖太長或交叉線太多說明你的圖在咬著一個(gè)過大的邏輯范圍不放。我常用的一個(gè)處理技巧是“聚合”。如果三條線同時(shí)指向同一個(gè)外部系統(tǒng)可以在圖上只畫一條線把它標(biāo)注為“統(tǒng)一依賴某服務(wù)”然后在圖的下方或文檔里注明更細(xì)的接口關(guān)系。如果五個(gè)節(jié)點(diǎn)之間存在網(wǎng)狀依賴那就把它們折疊成一個(gè)“子組件”節(jié)點(diǎn)在另一張“內(nèi)部細(xì)節(jié)圖”里展開。聚合的妙處在于它保留了讀者理解主干所需的全部信息。對評審人來說不關(guān)心子模塊內(nèi)部連了幾條線只要知道它是個(gè)獨(dú)立單元就足夠。等到需要深入單點(diǎn)細(xì)節(jié)時(shí)再翻開細(xì)節(jié)圖。這個(gè)思路和代碼重構(gòu)里“提取函數(shù)”的理念很像目的都是讓每一層抽象都保持在可理解的范圍。還有一種情況是圖過長一條縱向鏈路從頂部一直拉到頁面底部。這種圖多數(shù)因?yàn)闆]有分組。你把節(jié)點(diǎn)按照階段分成兩三塊每塊間留出明顯的間距留存或者在分組之間加一條明確的階段注釋就會(huì)好很多。人的眼睛需要一個(gè)“落腳點(diǎn)”分組就是那個(gè)落腳點(diǎn)。4.3 顏色雜亂與團(tuán)隊(duì)難維護(hù)從“禁止自由配色”開始團(tuán)隊(duì)合用一個(gè)文檔庫時(shí)最容易發(fā)生的是每個(gè)人畫圖都用自己喜歡的顏色。A同學(xué)把主要業(yè)務(wù)模塊涂成橙色B同學(xué)把同樣的模塊涂成藍(lán)色。視覺混亂還是小事更嚴(yán)重的是語義被破壞。當(dāng)一張圖里顏色不能代表類別時(shí)讀者只能靠文字去逐個(gè)識(shí)別節(jié)點(diǎn)閱讀效率極低。我定的團(tuán)隊(duì)約定是先確定角色再定顏色每個(gè)人的圖都要復(fù)用同一套模板。新增顏色必須經(jīng)過一次評審任何臨時(shí)想法都不能直接進(jìn)文檔。剛開始有人覺得太死板實(shí)際用了一段時(shí)間之后大家都開始受益。因?yàn)榭吹揭粋€(gè)顏色就知道它大概是數(shù)據(jù)庫、外部依賴還是主流程節(jié)點(diǎn)看圖速度明顯加快。這其實(shí)就是把個(gè)人審美換成了一種元認(rèn)知。另外畫布型工具協(xié)作時(shí)容易遇到兩個(gè)問題同一張圖多人同時(shí)編輯導(dǎo)致互相覆蓋以及源文件分散在個(gè)人電腦上導(dǎo)致版本混亂。我的建議是所有圖源文件統(tǒng)一收口到一個(gè)共享目錄和文檔同倉庫管理修改前先鎖定修改后記錄變更說明。如果確實(shí)需要多人高頻協(xié)同那就改用文本型工具并走代碼評審那道流程。這樣雖然多了一步但能避免很多無謂的返工。5. 最后說幾個(gè)提升圖質(zhì)量的意外技巧有幾個(gè)小技巧不在主流程里但很實(shí)用。第一個(gè)是給每張圖配一句“圖下注釋”。我見過太多圖光禿禿一張擺在那讀者需要自己猜它的作者到底想表達(dá)什么。其實(shí)只要在下方加一行小字比如“圖中從支付網(wǎng)關(guān)到訂單服務(wù)的雙線表示異步回執(zhí)鏈路下單主流程為灰色粗線”就能避免大量誤讀。這句話也逼著畫圖人自己再一次確認(rèn)這張圖最重要的事情是什么。第二個(gè)技巧是“先畫丑圖”。我發(fā)現(xiàn)如果中途過于在意美觀思路會(huì)被排版干擾。有些圖表設(shè)計(jì)走到瓶頸不是邏輯不對而是你已經(jīng)在擺位置和調(diào)樣式上花了大量心力腦子累了。先快速畫一版很丑的“骨圖”只表達(dá)節(jié)點(diǎn)和連線關(guān)系確認(rèn)邏輯無誤后再做樣式效率和效果都更好。這個(gè)順序不要顛倒。第三個(gè)技巧是善用圖層的注釋和陰影但要克制。給關(guān)鍵節(jié)點(diǎn)加一個(gè)注記框說明它的異常行為和降級策略往往比在正文里寫一大段更有效。而陰影、漸變、圓角這些裝飾元素能省則省。技術(shù)圖表不是海報(bào)信息傳遞優(yōu)先級永遠(yuǎn)排在視覺美觀前面。最后再放一句我踩過多次坑之后總結(jié)出來的經(jīng)驗(yàn)diagram-design 不是一個(gè)畫圖工具能解決的事情而是一套推導(dǎo)過程。從讀者、場景、結(jié)論出發(fā)經(jīng)過分層拆解、工具選型、結(jié)構(gòu)化清單、布局配色、終稿檢查最后形成可維護(hù)的圖與源文件。只要你把這套過程理順哪怕工具很簡陋畫出來的圖也不會(huì)難看到哪里去反過來說工具再強(qiáng)沒有這套過程最后也難逃一張“好看但沒人懂”的圖。