的圖表設(shè)計(jì)規(guī)范與實(shí)現(xiàn)方法)
1. 從一張草圖到一套系統(tǒng)diagram-design 到底在解決什么問(wèn)題第一次聽(tīng)到 “diagram-design” 這個(gè)詞很多人會(huì)下意識(shí)覺(jué)得它只是“畫(huà)圖”的另一種說(shuō)法。但真正在項(xiàng)目里被圖表折磨過(guò)的人知道畫(huà)圖只是冰山一角水面下藏著的是一整套關(guān)于信息結(jié)構(gòu)、視覺(jué)語(yǔ)言和協(xié)作流程的設(shè)計(jì)系統(tǒng)。我最早接觸這個(gè)概念是在一個(gè)跨平臺(tái)系統(tǒng)的重構(gòu)項(xiàng)目里當(dāng)時(shí)團(tuán)隊(duì)有五個(gè)人每個(gè)人畫(huà)出來(lái)的架構(gòu)圖風(fēng)格都不一樣有人用圓角矩形有人用直角有人把數(shù)據(jù)庫(kù)畫(huà)成圓柱有人畫(huà)成方塊連線有的帶箭頭有的不帶。結(jié)果就是每次評(píng)審會(huì)前半小時(shí)都在統(tǒng)一圖例而不是討論架構(gòu)本身。diagram-design 要解決的正是這種“圖不同源、意不同達(dá)”的混亂。簡(jiǎn)單來(lái)說(shuō)diagram-design 是一套面向圖表類內(nèi)容的設(shè)計(jì)規(guī)范與實(shí)現(xiàn)方法它覆蓋了從圖形語(yǔ)義定義、視覺(jué)樣式約束到生成工具鏈和協(xié)作流程的完整閉環(huán)。它能做的事情包括讓同一份邏輯結(jié)構(gòu)在不同工具、不同輸出格式下保持一致的視覺(jué)表達(dá)讓非設(shè)計(jì)背景的工程師也能產(chǎn)出專業(yè)級(jí)圖表讓圖表從“一次性消耗品”變成“可維護(hù)、可復(fù)用、可版本管理的資產(chǎn)”。這套方法適合誰(shuí)我認(rèn)為三類人最需要一是經(jīng)常寫技術(shù)方案、需要大量畫(huà)架構(gòu)圖和流程圖的開(kāi)發(fā)者二是負(fù)責(zé)設(shè)計(jì)系統(tǒng)建設(shè)、需要統(tǒng)一團(tuán)隊(duì)視覺(jué)語(yǔ)言的設(shè)計(jì)師三是做技術(shù)文檔、教程內(nèi)容需要批量產(chǎn)出高質(zhì)量配圖的創(chuàng)作者。我之所以對(duì)這個(gè)標(biāo)題有感覺(jué)是因?yàn)檫^(guò)去幾年里我見(jiàn)過(guò)太多項(xiàng)目在“畫(huà)圖”這件事上反復(fù)踩坑。有人花兩天時(shí)間調(diào)一張流程圖的間距有人因?yàn)閳D表源文件丟失導(dǎo)致文檔無(wú)法更新還有人把同一套架構(gòu)在不同文檔里畫(huà)出了三個(gè)版本。diagram-design 的價(jià)值不在于讓你畫(huà)得更快而在于讓你畫(huà)得更“穩(wěn)”——穩(wěn)定輸出、穩(wěn)定維護(hù)、穩(wěn)定協(xié)作。接下來(lái)我會(huì)把這套方法拆開(kāi)從設(shè)計(jì)思路、核心細(xì)節(jié)、實(shí)操落地到問(wèn)題排查完整講一遍我自己的理解和實(shí)踐。2. 內(nèi)容整體設(shè)計(jì)與思路拆解為什么圖表需要“設(shè)計(jì)系統(tǒng)”2.1 圖表混亂的根源缺少語(yǔ)義層與樣式層的分離大多數(shù)人在畫(huà)圖時(shí)習(xí)慣是“所見(jiàn)即所得”地直接操作圖形拖一個(gè)矩形改個(gè)顏色加個(gè)文字連一條線。這種方式在單張圖里沒(méi)問(wèn)題但一旦圖表數(shù)量上去、參與人數(shù)變多問(wèn)題就會(huì)集中爆發(fā)。核心原因是語(yǔ)義層和樣式層被混在了一起。所謂語(yǔ)義層是指這個(gè)圖形代表什么——它是一個(gè)服務(wù)、一個(gè)數(shù)據(jù)庫(kù)、一個(gè)決策節(jié)點(diǎn)還是一個(gè)外部系統(tǒng)。所謂樣式層是指它長(zhǎng)什么樣——顏色、邊框、圓角、字體、線型。當(dāng)這兩層混在一起時(shí)你想把“所有數(shù)據(jù)庫(kù)”從藍(lán)色改成綠色就得一張一張圖去改你想讓“決策節(jié)點(diǎn)”統(tǒng)一用菱形就得靠人肉記憶和檢查。diagram-design 的第一個(gè)設(shè)計(jì)決策就是強(qiáng)制分離語(yǔ)義與樣式。具體做法是先定義一套圖形語(yǔ)義詞匯表比如“服務(wù)”“存儲(chǔ)”“隊(duì)列”“網(wǎng)關(guān)”“用戶”“外部依賴”等每個(gè)詞匯對(duì)應(yīng)一個(gè)抽象的圖形角色然后再定義一套樣式映射規(guī)則規(guī)定每個(gè)角色在不同主題下的視覺(jué)表現(xiàn)。這樣當(dāng)你調(diào)整樣式時(shí)只需要改映射表所有圖表自動(dòng)更新。這個(gè)思路借鑒了前端開(kāi)發(fā)里“結(jié)構(gòu)與表現(xiàn)分離”的經(jīng)典原則。我在一個(gè)模擬項(xiàng)目里試過(guò)這套方法當(dāng)時(shí)有大約四十張架構(gòu)圖需要統(tǒng)一改版如果按傳統(tǒng)方式逐張修改至少需要兩天而因?yàn)榍捌谧隽苏Z(yǔ)義與樣式的分離我只改了映射配置里的六個(gè)顏色變量和兩個(gè)線型參數(shù)四十分鐘內(nèi)全部圖表重新生成完畢。這個(gè)效率差距就是設(shè)計(jì)系統(tǒng)帶來(lái)的直接收益。2.2 為什么選擇“約束優(yōu)先”而不是“自由優(yōu)先”很多人對(duì)設(shè)計(jì)系統(tǒng)有誤解覺(jué)得它是在限制創(chuàng)造力。但在圖表這個(gè)場(chǎng)景里約束恰恰是效率的來(lái)源。你想想如果每個(gè)人都可以自由選擇顏色、字體、線型、間距那評(píng)審時(shí)討論的就不是內(nèi)容而是“這個(gè)藍(lán)色是不是太淺了”“這個(gè)箭頭是不是太粗了”。diagram-design 的思路是把那些不該由個(gè)人決定的視覺(jué)細(xì)節(jié)用規(guī)范鎖死把精力留給真正需要?jiǎng)?chuàng)造力的部分——信息結(jié)構(gòu)的組織和表達(dá)。具體來(lái)說(shuō)約束優(yōu)先體現(xiàn)在幾個(gè)層面。第一顏色數(shù)量受限一套圖表主題通常只允許三到五個(gè)主色加上兩到三個(gè)中性色避免彩虹式配色。第二圖形形狀受限每種語(yǔ)義角色只對(duì)應(yīng)一種基礎(chǔ)形狀不允許隨意替換。第三間距和尺寸受限網(wǎng)格系統(tǒng)預(yù)先定義好所有元素必須對(duì)齊到網(wǎng)格。第四字體和字號(hào)受限通常只允許兩到三種字號(hào)分別用于標(biāo)題、標(biāo)簽和注釋。這些約束看起來(lái)死板但實(shí)際用起來(lái)會(huì)發(fā)現(xiàn)它把“決策成本”降到了最低。你不需要每次畫(huà)圖都思考“這個(gè)節(jié)點(diǎn)用什么顏色”因?yàn)橐?guī)范已經(jīng)告訴你了。你只需要思考“這個(gè)節(jié)點(diǎn)在語(yǔ)義上屬于哪一類”。我在帶新人的時(shí)候最常聽(tīng)到的反饋就是“以前畫(huà)圖最怕調(diào)樣式現(xiàn)在反而覺(jué)得輕松了因?yàn)椴挥眠x了?!?.3 工具鏈選型的核心考量文本驅(qū)動(dòng)與版本可控diagram-design 在工具選型上有一個(gè)很明確的方向優(yōu)先選擇文本驅(qū)動(dòng)的圖表生成方式而不是純圖形界面拖拽。為什么因?yàn)槲谋掘?qū)動(dòng)意味著圖表源文件是純文本可以納入版本管理可以做 diff可以代碼評(píng)審可以自動(dòng)化生成。而純圖形界面的源文件通常是二進(jìn)制或私有格式無(wú)法有效追蹤變更協(xié)作時(shí)只能靠“發(fā)文件—改文件—再發(fā)文件”的原始方式。目前主流的文本驅(qū)動(dòng)圖表方案有幾類一類是基于特定DSL的比如用類似代碼的方式描述圖表結(jié)構(gòu)一類是基于通用圖形描述語(yǔ)言的比如用XML或JSON定義節(jié)點(diǎn)和連線還有一類是基于代碼生成庫(kù)的比如用Python或JavaScript腳本動(dòng)態(tài)生成圖表。我在不同項(xiàng)目里都試過(guò)最終傾向于DSL加渲染管線的組合用簡(jiǎn)潔的DSL描述圖表邏輯用渲染管線負(fù)責(zé)樣式應(yīng)用和格式輸出。這樣既保證了源文件的可讀性和可維護(hù)性又保留了輸出格式的靈活性——同一份源文件可以渲染成矢量圖、位圖也可以嵌入網(wǎng)頁(yè)。注意選擇文本驅(qū)動(dòng)方案時(shí)一定要確認(rèn)渲染管線支持你需要的輸出格式。有些方案只支持單一格式后期轉(zhuǎn)換會(huì)很麻煩。2.4 協(xié)作流程的設(shè)計(jì)從“個(gè)人創(chuàng)作”到“團(tuán)隊(duì)資產(chǎn)”diagram-design 的最后一個(gè)設(shè)計(jì)維度是協(xié)作流程。傳統(tǒng)畫(huà)圖是個(gè)人行為一個(gè)人畫(huà)完導(dǎo)出圖片發(fā)給別人。圖表源文件往往只存在于個(gè)人電腦里別人想改也改不了。diagram-design 提倡的是圖表即代碼的協(xié)作模式圖表源文件放在共享倉(cāng)庫(kù)里任何人可以提交修改通過(guò)評(píng)審后合并自動(dòng)觸發(fā)渲染和發(fā)布。這套流程的好處是顯而易見(jiàn)的。第一變更可追溯誰(shuí)在什么時(shí)候改了哪個(gè)節(jié)點(diǎn)一目了然。第二評(píng)審可操作評(píng)審者可以直接在源文件上提意見(jiàn)而不是對(duì)著圖片說(shuō)“這里改一下”。第三復(fù)用可實(shí)現(xiàn)公共組件和樣式可以被多個(gè)圖表引用改一處即改全部。第四發(fā)布可自動(dòng)化源文件合并后自動(dòng)生成最新圖表并更新到文檔站點(diǎn)不需要手動(dòng)導(dǎo)出替換。我在一個(gè)文檔項(xiàng)目里落地過(guò)這套流程最直觀的感受是圖表不再是“一次性消耗品”而是變成了和代碼一樣的長(zhǎng)期資產(chǎn)。半年后回頭看每一張圖的演變歷史都清清楚楚想回滾到某個(gè)版本也毫無(wú)壓力。3. 核心細(xì)節(jié)解析與實(shí)操要點(diǎn)圖形語(yǔ)義、樣式映射與網(wǎng)格系統(tǒng)3.1 圖形語(yǔ)義詞匯表的設(shè)計(jì)方法圖形語(yǔ)義詞匯表是整套 diagram-design 的地基。它的作用是定義“圖表里可能出現(xiàn)哪些角色”以及“每個(gè)角色的含義邊界”。設(shè)計(jì)這張表的時(shí)候我建議從三個(gè)維度去梳理實(shí)體維度、關(guān)系維度、行為維度。實(shí)體維度包括系統(tǒng)中存在的各類對(duì)象比如用戶、服務(wù)、數(shù)據(jù)庫(kù)、緩存、隊(duì)列、外部系統(tǒng)等。關(guān)系維度包括對(duì)象之間的連接方式比如調(diào)用、依賴、數(shù)據(jù)流、控制流等。行為維度包括流程中的動(dòng)作和決策比如處理、判斷、等待、并行等。每個(gè)維度下的詞匯不宜過(guò)多通??刂圃谑绞鍌€(gè)以內(nèi)太多了記不住太少了不夠用。我自己的做法是先列一個(gè)“高頻角色清單”把項(xiàng)目里最常出現(xiàn)的圖形角色寫下來(lái)然后合并同類項(xiàng)。比如“微服務(wù)”“單體服務(wù)”“后臺(tái)服務(wù)”可以統(tǒng)一為“服務(wù)”角色通過(guò)標(biāo)簽區(qū)分具體類型。這樣做的目的是保持語(yǔ)義層的簡(jiǎn)潔和穩(wěn)定避免詞匯表膨脹。語(yǔ)義角色含義說(shuō)明基礎(chǔ)形狀典型標(biāo)簽示例服務(wù)提供功能的邏輯單元圓角矩形訂單服務(wù)、用戶服務(wù)存儲(chǔ)持久化數(shù)據(jù)的組件圓柱體主庫(kù)、從庫(kù)、緩存隊(duì)列異步消息通道橫向管道事件隊(duì)列、任務(wù)隊(duì)列網(wǎng)關(guān)流量入口與路由六邊形API網(wǎng)關(guān)、接入層用戶系統(tǒng)外部參與者圓形終端用戶、管理員外部依賴不受控的外部系統(tǒng)虛線矩形支付平臺(tái)、短信平臺(tái)這張表一旦定下來(lái)就作為團(tuán)隊(duì)共識(shí)存在。后續(xù)所有圖表都從這張表里選角色不允許臨時(shí)發(fā)明新形狀。如果確實(shí)遇到表里沒(méi)有的角色先討論是否可以用現(xiàn)有角色加標(biāo)簽表達(dá)實(shí)在不行再走變更流程新增。3.2 樣式映射規(guī)則讓同一份邏輯適配不同場(chǎng)景樣式映射是連接語(yǔ)義層和視覺(jué)層的橋梁。它的核心邏輯是語(yǔ)義角色到視覺(jué)屬性的映射關(guān)系集中定義在一處而不是分散在每張圖里。這樣做的直接好處是當(dāng)你需要調(diào)整視覺(jué)風(fēng)格時(shí)只需要改映射規(guī)則所有圖表自動(dòng)生效。映射規(guī)則通常包含以下幾類屬性填充色、邊框色、邊框線型、邊框粗細(xì)、圓角半徑、文字顏色、文字字號(hào)、圖標(biāo)。每一類屬性都對(duì)應(yīng)一組預(yù)設(shè)值而不是任意值。比如填充色只允許從主題色板里選邊框粗細(xì)只允許“細(xì)”“中”“粗”三檔。這種“有限選項(xiàng)”的設(shè)計(jì)是為了防止樣式漂移。我在實(shí)際項(xiàng)目里會(huì)把映射規(guī)則寫成一個(gè)配置文件格式可以是JSON或YAML。下面是一個(gè)簡(jiǎn)化示例theme: default roles: service: fill: #E8F0FE stroke: #1A73E8 strokeWidth: 2 radius: 8 textColor: #202124 fontSize: 14 storage: fill: #E6F4EA stroke: #137333 strokeWidth: 2 radius: 0 textColor: #202124 fontSize: 14 queue: fill: #FEF7E0 stroke: #B06000 strokeWidth: 2 radius: 4 textColor: #202124 fontSize: 14這個(gè)配置文件的好處是換主題只需要換一個(gè)文件。比如要做一套深色主題的圖表只需要復(fù)制一份配置改掉顏色值即可圖表源文件完全不用動(dòng)。提示映射規(guī)則里的顏色值建議使用設(shè)計(jì)令牌design token的方式管理不要直接寫死十六進(jìn)制值。這樣后續(xù)做主題切換或品牌適配時(shí)會(huì)更靈活。3.3 網(wǎng)格系統(tǒng)與間距規(guī)范讓圖表“看起來(lái)舒服”的秘密很多人畫(huà)圖時(shí)忽略網(wǎng)格和間距覺(jué)得“差不多就行”。但圖表看起來(lái)是否專業(yè)很大程度上取決于對(duì)齊和間距的一致性。diagram-design 里有一套明確的網(wǎng)格系統(tǒng)通常以8像素為基準(zhǔn)單位所有元素的尺寸、位置、間距都必須是8的倍數(shù)。為什么是8因?yàn)?既能被2整除也能被4整除適配多種屏幕密度時(shí)不容易出現(xiàn)半像素模糊。具體規(guī)范包括節(jié)點(diǎn)寬度通常是網(wǎng)格單位的整數(shù)倍比如160、240、320節(jié)點(diǎn)高度同理節(jié)點(diǎn)之間的水平間距和垂直間距分別定義標(biāo)準(zhǔn)值比如水平間距48垂直間距64連線與節(jié)點(diǎn)之間的留白也有最小值避免線貼著邊框。這些數(shù)值看起來(lái)瑣碎但正是它們讓圖表從“能看”變成“好看”。我在調(diào)整一套舊圖表時(shí)做過(guò)對(duì)比同樣的邏輯結(jié)構(gòu)一張按自由間距畫(huà)一張按網(wǎng)格規(guī)范畫(huà)后者在視覺(jué)上的清晰度明顯更高。讀者的眼睛不需要在參差不齊的間距里“找路”信息獲取效率自然就上去了。3.4 連線與箭頭的語(yǔ)義規(guī)范連線是圖表里最容易被忽視、也最容易出問(wèn)題的部分。diagram-design 對(duì)連線有明確的語(yǔ)義規(guī)范不同的關(guān)系類型用不同的線型和箭頭表示。比如同步調(diào)用用實(shí)線加實(shí)心箭頭異步消息用虛線加空心箭頭數(shù)據(jù)流用帶圓點(diǎn)的實(shí)線依賴關(guān)系用點(diǎn)線加開(kāi)放箭頭。這樣讀者不需要看圖例就能大致判斷關(guān)系類型。連線的另一個(gè)規(guī)范是走線規(guī)則優(yōu)先走直線直線走不通走直角折線盡量避免斜線和曲線。走線要避開(kāi)節(jié)點(diǎn)不允許穿過(guò)節(jié)點(diǎn)內(nèi)部。多條連線并行時(shí)要保持等距不允許交叉混亂。這些規(guī)則聽(tīng)起來(lái)嚴(yán)格但實(shí)際畫(huà)的時(shí)候因?yàn)楣ぞ呖梢宰詣?dòng)路由執(zhí)行成本并不高。我在排查一張復(fù)雜流程圖時(shí)發(fā)現(xiàn)問(wèn)題往往出在連線而不是節(jié)點(diǎn)上。節(jié)點(diǎn)再多只要排列整齊讀者還能跟上但連線一旦交叉混亂整個(gè)圖的可讀性就崩了。所以我的經(jīng)驗(yàn)是寧可多花時(shí)間調(diào)整連線也不要讓線交叉。4. 實(shí)操過(guò)程與核心環(huán)節(jié)實(shí)現(xiàn)從零搭建一套圖表生成管線4.1 環(huán)境準(zhǔn)備與工具鏈搭建要落地 diagram-design第一步是搭一套可用的工具鏈。我的建議是選擇文本描述加命令行渲染的組合這樣既能保證源文件可版本管理又能方便地集成到自動(dòng)化流程里。具體來(lái)說(shuō)需要準(zhǔn)備三樣?xùn)|西一個(gè)文本編輯器或IDE用于編寫圖表源文件一個(gè)渲染引擎用于把源文件轉(zhuǎn)成圖片一個(gè)版本管理工具用于追蹤變更。渲染引擎的選擇上我傾向于支持DSL的方案因?yàn)镈SL比通用圖形語(yǔ)言更簡(jiǎn)潔寫起來(lái)更像“描述邏輯”而不是“描述圖形”。安裝過(guò)程通常很簡(jiǎn)單通過(guò)包管理器安裝命令行工具即可。安裝完成后用一個(gè)小例子驗(yàn)證渲染是否正常。# 安裝渲染工具以某通用包管理器為例 package-manager install diagram-renderer # 驗(yàn)證安裝 diagram-renderer --version # 渲染一個(gè)測(cè)試文件 diagram-renderer render test.dgm -o test.svg環(huán)境搭好后我建議先不要急著畫(huà)復(fù)雜圖而是用三五個(gè)節(jié)點(diǎn)的小圖跑通整個(gè)流程寫源文件、渲染、查看輸出、修改、重新渲染。這個(gè)循環(huán)跑順了后面畫(huà)大圖只是規(guī)模問(wèn)題。4.2 圖表源文件的編寫規(guī)范與結(jié)構(gòu)圖表源文件是整套流程的核心資產(chǎn)它的編寫質(zhì)量直接決定了后續(xù)維護(hù)成本。我總結(jié)了幾條編寫規(guī)范都是踩坑之后總結(jié)出來(lái)的。第一文件命名要有意義。不要用“圖1”“新建圖表”這種名字而要用“訂單系統(tǒng)架構(gòu)”“用戶注冊(cè)流程”這種描述性名稱。文件名里可以包含版本號(hào)或日期方便追蹤。第二節(jié)點(diǎn)定義要包含語(yǔ)義角色和標(biāo)簽。語(yǔ)義角色決定樣式標(biāo)簽決定顯示文字。兩者分開(kāi)寫不要混在一起。第三布局信息盡量少寫。如果渲染引擎支持自動(dòng)布局就不要手動(dòng)指定每個(gè)節(jié)點(diǎn)的坐標(biāo)。手動(dòng)坐標(biāo)雖然精確但一旦節(jié)點(diǎn)增減就得重新調(diào)整維護(hù)成本極高。自動(dòng)布局雖然不完美但勝在穩(wěn)定。第四注釋要寫清楚。圖表源文件也是代碼該注釋的地方要注釋。比如某個(gè)節(jié)點(diǎn)為什么放在這個(gè)分組里某條連線為什么用虛線都值得寫一句說(shuō)明。下面是一個(gè)簡(jiǎn)化后的源文件示例描述一個(gè)用戶注冊(cè)流程diagram: 用戶注冊(cè)流程 nodes: - id: user role: user label: 用戶 - id: gateway role: gateway label: 接入網(wǎng)關(guān) - id: auth role: service label: 認(rèn)證服務(wù) - id: db role: storage label: 用戶庫(kù) - id: queue role: queue label: 歡迎郵件隊(duì)列 edges: - from: user to: gateway type: sync label: 提交注冊(cè) - from: gateway to: auth type: sync label: 轉(zhuǎn)發(fā)請(qǐng)求 - from: auth to: db type: data label: 寫入用戶 - from: auth to: queue type: async label: 發(fā)送事件這個(gè)文件讀起來(lái)幾乎就是自然語(yǔ)言任何人拿到都能看懂邏輯。渲染出來(lái)的圖樣式由映射規(guī)則統(tǒng)一控制不需要在源文件里寫任何顏色或尺寸。4.3 渲染管線的配置與自動(dòng)化集成源文件寫好后下一步是配置渲染管線。渲染管線通常包含三個(gè)階段解析、布局、繪制。解析階段把源文件轉(zhuǎn)成內(nèi)部數(shù)據(jù)結(jié)構(gòu)布局階段計(jì)算每個(gè)節(jié)點(diǎn)的位置和連線的路徑繪制階段應(yīng)用樣式并輸出最終圖形。大多數(shù)渲染引擎會(huì)把這幾個(gè)階段封裝好你只需要提供配置。配置里我建議關(guān)注幾個(gè)關(guān)鍵參數(shù)輸出格式矢量圖優(yōu)先位圖作為補(bǔ)充、輸出尺寸根據(jù)使用場(chǎng)景定文檔配圖通常寬度在800到1200像素之間、主題對(duì)應(yīng)前面說(shuō)的樣式映射文件、布局算法分層布局適合流程圖力導(dǎo)向布局適合關(guān)系圖。這些參數(shù)可以寫在配置文件里也可以通過(guò)命令行參數(shù)傳入。自動(dòng)化集成是這套流程真正發(fā)揮威力的地方。我通常會(huì)把渲染命令寫進(jìn)構(gòu)建腳本每次源文件變更后自動(dòng)觸發(fā)渲染。如果團(tuán)隊(duì)有文檔站點(diǎn)還可以把渲染產(chǎn)物直接發(fā)布到站點(diǎn)上。下面是一個(gè)簡(jiǎn)化的自動(dòng)化腳本示例#!/bin/bash # 遍歷所有圖表源文件逐個(gè)渲染 for file in diagrams/*.dgm; do name$(basename $file .dgm) diagram-renderer render $file \ --theme themes/default.yaml \ --format svg \ --output output/${name}.svg done echo 所有圖表渲染完成這個(gè)腳本可以掛在持續(xù)集成流程里每次提交后自動(dòng)執(zhí)行。這樣團(tuán)隊(duì)里任何人改了圖表源文件最新版本都會(huì)自動(dòng)生成不需要手動(dòng)操作。4.4 從單張圖到圖表庫(kù)資產(chǎn)化管理的實(shí)操當(dāng)圖表數(shù)量積累到一定程度就需要考慮資產(chǎn)化管理。我的做法是建立一個(gè)圖表庫(kù)目錄結(jié)構(gòu)按業(yè)務(wù)域或系統(tǒng)模塊分類存放源文件公共組件和主題單獨(dú)放在頂層目錄。目錄結(jié)構(gòu)大致如下diagrams/ themes/ default.yaml dark.yaml components/ common-roles.yaml order-system/ architecture.dgm payment-flow.dgm user-system/ registration-flow.dgm login-flow.dgm這種結(jié)構(gòu)的好處是公共樣式和組件集中管理業(yè)務(wù)圖表按域隔離。修改主題時(shí)所有圖表統(tǒng)一生效修改某個(gè)業(yè)務(wù)域的圖表時(shí)不會(huì)影響其他域。我還會(huì)在圖表庫(kù)里放一個(gè)索引文件列出所有圖表的名稱、用途、最后更新時(shí)間和負(fù)責(zé)人方便團(tuán)隊(duì)查找和復(fù)用。注意圖表庫(kù)一定要有明確的負(fù)責(zé)人和更新流程。否則時(shí)間一長(zhǎng)圖表庫(kù)會(huì)變成“沒(méi)人敢動(dòng)的歷史遺留”反而增加維護(hù)負(fù)擔(dān)。5. 常見(jiàn)問(wèn)題與排查技巧實(shí)錄那些文檔里不會(huì)寫的坑5.1 渲染結(jié)果與預(yù)期不符的排查思路這是最常見(jiàn)的問(wèn)題源文件寫好了渲染出來(lái)卻發(fā)現(xiàn)節(jié)點(diǎn)位置不對(duì)、連線交叉、文字溢出。排查這類問(wèn)題我通常按以下順序檢查。第一檢查源文件語(yǔ)法。很多時(shí)候是縮進(jìn)或標(biāo)點(diǎn)問(wèn)題導(dǎo)致解析異常。文本驅(qū)動(dòng)的方案對(duì)語(yǔ)法敏感一個(gè)多余的冒號(hào)或缺失的引號(hào)都可能讓整個(gè)文件解析失敗。建議用編輯器的語(yǔ)法高亮功能輔助檢查。第二檢查布局算法配置。不同的布局算法對(duì)同一份數(shù)據(jù)的處理結(jié)果差異很大。如果節(jié)點(diǎn)位置混亂可能是布局算法選錯(cuò)了。流程圖用分層布局關(guān)系圖用力導(dǎo)向布局樹(shù)形結(jié)構(gòu)用樹(shù)形布局選對(duì)了算法布局問(wèn)題就解決了一大半。第三檢查樣式映射。如果顏色或形狀不對(duì)多半是映射規(guī)則沒(méi)生效。檢查主題文件路徑是否正確角色名稱是否拼寫一致。我遇到過(guò)好幾次因?yàn)榻巧笮懖灰恢聦?dǎo)致樣式?jīng)]應(yīng)用的情況排查了半天才發(fā)現(xiàn)。第四檢查輸出格式。有些渲染引擎在不同輸出格式下的表現(xiàn)不一致比如SVG正常但PNG文字偏移。如果遇到這種情況先確認(rèn)是不是格式特有問(wèn)題再?zèng)Q定是換格式還是調(diào)參數(shù)。5.2 圖表可讀性差的典型癥狀與改進(jìn)方法圖表畫(huà)出來(lái)了但讀者說(shuō)“看不懂”這是比渲染失敗更棘手的問(wèn)題??勺x性差通常有幾個(gè)典型癥狀節(jié)點(diǎn)太多太密、連線交叉嚴(yán)重、文字太小或太長(zhǎng)、顏色對(duì)比度不夠、缺少視覺(jué)層次。針對(duì)節(jié)點(diǎn)太多的問(wèn)題我的建議是拆圖。一張圖只講一件事超過(guò)十五個(gè)節(jié)點(diǎn)就考慮拆成兩張。拆圖的邏輯可以按流程階段拆也可以按系統(tǒng)層次拆。拆完之后用一張總覽圖串聯(lián)總覽圖里只放高層模塊細(xì)節(jié)放到分圖里。針對(duì)連線交叉的問(wèn)題調(diào)整節(jié)點(diǎn)順序往往比調(diào)整連線更有效。把關(guān)聯(lián)緊密的節(jié)點(diǎn)放在相鄰位置交叉自然就少了。如果實(shí)在無(wú)法避免交叉可以用“跳線”符號(hào)表示線不相交但跳線本身也會(huì)增加視覺(jué)負(fù)擔(dān)能不用就不用。針對(duì)文字問(wèn)題核心原則是標(biāo)簽要短。節(jié)點(diǎn)標(biāo)簽控制在六個(gè)字以內(nèi)連線標(biāo)簽控制在四個(gè)字以內(nèi)。如果信息量確實(shí)大把詳細(xì)說(shuō)明放到圖外的注釋里不要塞進(jìn)圖里。字號(hào)方面正文標(biāo)簽不小于12像素標(biāo)題不小于16像素確保在常見(jiàn)閱讀距離下清晰可辨。針對(duì)顏色問(wèn)題記住一個(gè)原則顏色是用來(lái)區(qū)分語(yǔ)義的不是用來(lái)裝飾的。同一張圖里顏色種類不超過(guò)五種且要有明顯的對(duì)比度差異。淺色背景配深色文字深色背景配淺色文字確??勺x性。5.3 團(tuán)隊(duì)協(xié)作中的版本沖突與合并策略當(dāng)多人同時(shí)修改圖表源文件時(shí)版本沖突幾乎不可避免。文本驅(qū)動(dòng)方案的好處是沖突可以用常規(guī)的代碼合并工具處理。但圖表源文件有其特殊性合并時(shí)需要額外注意幾點(diǎn)。第一節(jié)點(diǎn)ID要保持穩(wěn)定。如果兩個(gè)人同時(shí)新增節(jié)點(diǎn)且用了相同的ID合并后會(huì)出現(xiàn)重復(fù)定義。建議在ID里加入業(yè)務(wù)前綴比如“order-service”“user-db”降低沖突概率。第二布局信息盡量不寫進(jìn)源文件。如果源文件里包含坐標(biāo)兩個(gè)人同時(shí)調(diào)整布局就會(huì)沖突。用自動(dòng)布局可以規(guī)避這個(gè)問(wèn)題。第三樣式修改走主題文件。如果每個(gè)人都直接改源文件里的樣式?jīng)_突會(huì)非常頻繁。把樣式集中在主題文件里源文件只寫語(yǔ)義沖突面就小很多。第四建立評(píng)審機(jī)制。圖表源文件的修改也應(yīng)該走評(píng)審流程至少讓另一個(gè)人看一眼。評(píng)審時(shí)重點(diǎn)關(guān)注語(yǔ)義是否正確、命名是否規(guī)范、是否復(fù)用了已有組件。5.4 常見(jiàn)問(wèn)題速查表問(wèn)題現(xiàn)象可能原因排查方法解決建議渲染失敗無(wú)輸出源文件語(yǔ)法錯(cuò)誤檢查縮進(jìn)、標(biāo)點(diǎn)、引號(hào)用編輯器語(yǔ)法檢查逐段注釋定位節(jié)點(diǎn)位置混亂布局算法不匹配確認(rèn)圖表類型與算法對(duì)應(yīng)關(guān)系流程圖用分層布局關(guān)系圖用力導(dǎo)向樣式不生效角色名不一致對(duì)比源文件與主題文件的角色名統(tǒng)一命名規(guī)范大小寫敏感文字溢出節(jié)點(diǎn)標(biāo)簽過(guò)長(zhǎng)或字號(hào)過(guò)大檢查標(biāo)簽字?jǐn)?shù)和字號(hào)設(shè)置縮短標(biāo)簽或調(diào)大節(jié)點(diǎn)尺寸連線交叉嚴(yán)重節(jié)點(diǎn)順序不合理觀察連線走向找出交叉點(diǎn)調(diào)整節(jié)點(diǎn)順序或拆分圖表輸出圖片模糊輸出格式或尺寸問(wèn)題檢查輸出格式是否為矢量?jī)?yōu)先輸出SVG位圖提高分辨率多人修改沖突源文件結(jié)構(gòu)不合理查看沖突文件的具體差異分離樣式與語(yǔ)義穩(wěn)定節(jié)點(diǎn)ID圖表更新后文檔未同步自動(dòng)化流程未觸發(fā)檢查構(gòu)建腳本和觸發(fā)條件配置提交后自動(dòng)渲染和發(fā)布5.5 我踩過(guò)的三個(gè)典型坑第一個(gè)坑是過(guò)度依賴手動(dòng)布局。早期我為了讓每張圖都“完美”手動(dòng)調(diào)整每個(gè)節(jié)點(diǎn)的坐標(biāo)。結(jié)果有一次需求變更需要在一個(gè)流程中間插入兩個(gè)節(jié)點(diǎn)我花了整整一個(gè)下午重新調(diào)整所有坐標(biāo)。后來(lái)改用自動(dòng)布局雖然初始效果不如手動(dòng)精細(xì)但維護(hù)成本降低了十倍不止。我的教訓(xùn)是圖表的可維護(hù)性比一次性美觀更重要。第二個(gè)坑是主題文件沒(méi)有版本管理。有一段時(shí)間主題文件直接放在本地沒(méi)有納入版本庫(kù)。結(jié)果有一次換電腦主題文件丟了所有圖表渲染出來(lái)都是默認(rèn)樣式和之前完全不一樣。從那以后我把主題文件、組件文件、源文件全部納入同一個(gè)版本庫(kù)確保任何一臺(tái)機(jī)器拉下來(lái)都能渲染出一致的結(jié)果。第三個(gè)坑是忽略了圖表的可訪問(wèn)性。有一次做技術(shù)分享投影儀色彩偏差嚴(yán)重我圖里用淺藍(lán)和淺綠區(qū)分的兩類節(jié)點(diǎn)在投影上幾乎看不出區(qū)別。后來(lái)我在主題里增加了“高對(duì)比度”模式確保在低質(zhì)量顯示設(shè)備上也能分辨。這個(gè)經(jīng)驗(yàn)告訴我圖表設(shè)計(jì)要考慮最差的顯示環(huán)境而不是假設(shè)所有人都在專業(yè)顯示器上看。6. 圖表設(shè)計(jì)的進(jìn)階方向從靜態(tài)圖到交互式表達(dá)6.1 交互式圖表的適用場(chǎng)景與實(shí)現(xiàn)思路靜態(tài)圖表適合文檔和打印但有些場(chǎng)景下交互式圖表能提供更好的閱讀體驗(yàn)。比如大型系統(tǒng)的架構(gòu)圖節(jié)點(diǎn)上百個(gè)靜態(tài)圖怎么看都擁擠但做成可縮放、可點(diǎn)擊、可搜索的交互式圖表讀者就能按需探索。再比如流程復(fù)雜的業(yè)務(wù)圖讀者可能只關(guān)心某一條路徑交互式高亮能讓信息獲取更高效。實(shí)現(xiàn)交互式圖表的技術(shù)路線有幾條。一條是矢量圖加腳本渲染出SVG然后用JavaScript添加交互邏輯比如點(diǎn)擊節(jié)點(diǎn)顯示詳情、鼠標(biāo)懸停高亮關(guān)聯(lián)連線。另一條是圖表庫(kù)直接渲染用前端圖表庫(kù)讀取結(jié)構(gòu)化數(shù)據(jù)在瀏覽器里動(dòng)態(tài)繪制。還有一條是靜態(tài)圖加圖層把不同層次的信息拆成多個(gè)圖層通過(guò)切換圖層實(shí)現(xiàn)交互效果。我個(gè)人的經(jīng)驗(yàn)是交互式圖表適合放在文檔站點(diǎn)或內(nèi)部知識(shí)庫(kù)里不適合放在正式文檔或打印材料里。因?yàn)榻换ナ綀D表依賴運(yùn)行環(huán)境一旦脫離瀏覽器就無(wú)法使用。所以我的建議是核心圖表保持靜態(tài)增強(qiáng)體驗(yàn)用交互兩者互補(bǔ)而不是替代。6.2 圖表與文檔的深度集成diagram-design 的最終目標(biāo)不是產(chǎn)出孤立的圖片而是讓圖表成為文檔的有機(jī)組成部分。這意味著圖表要能隨文檔一起版本管理、一起構(gòu)建、一起發(fā)布。我目前的做法是圖表源文件和文檔源文件放在同一個(gè)倉(cāng)庫(kù)里文檔構(gòu)建時(shí)自動(dòng)調(diào)用渲染管線生成圖表并嵌入到對(duì)應(yīng)位置。這種集成方式的好處是文檔里的圖表永遠(yuǎn)是最新的不會(huì)出現(xiàn)“文檔更新了但圖沒(méi)更新”的情況。而且因?yàn)閳D表是自動(dòng)生成的修改圖表只需要改源文件不需要手動(dòng)導(dǎo)出替換。對(duì)于技術(shù)文檔這種更新頻繁的場(chǎng)景這種集成方式能省下大量重復(fù)勞動(dòng)。集成時(shí)需要注意幾點(diǎn)圖表輸出路徑要和文檔引用路徑一致渲染失敗時(shí)要有明確的報(bào)錯(cuò)信息避免文檔構(gòu)建靜默失敗圖表緩存策略要合理避免每次構(gòu)建都重新渲染所有圖表浪費(fèi)時(shí)間。6.3 圖表設(shè)計(jì)規(guī)范的持續(xù)演進(jìn)設(shè)計(jì)規(guī)范不是一成不變的。隨著項(xiàng)目發(fā)展、團(tuán)隊(duì)變化、工具更新規(guī)范也需要持續(xù)演進(jìn)。我的經(jīng)驗(yàn)是每季度回顧一次圖表規(guī)范看看有沒(méi)有需要調(diào)整的地方?;仡檿r(shí)重點(diǎn)關(guān)注幾個(gè)信號(hào)團(tuán)隊(duì)是否頻繁繞過(guò)規(guī)范、是否有新的圖表類型無(wú)法用現(xiàn)有角色表達(dá)、是否有樣式映射不再適用、是否有新的輸出格式需求。規(guī)范演進(jìn)的原則是小步快跑不要大改。每次只調(diào)整一兩個(gè)點(diǎn)觀察一段時(shí)間再?zèng)Q定是否繼續(xù)。大改會(huì)導(dǎo)致所有圖表需要重新適配成本太高。另外規(guī)范變更要有記錄說(shuō)明為什么改、改了什么、影響范圍是什么方便后來(lái)人理解。我在一個(gè)長(zhǎng)期項(xiàng)目里維護(hù)圖表規(guī)范三年最大的體會(huì)是規(guī)范的生命力在于執(zhí)行。如果規(guī)范定了但沒(méi)人遵守那還不如不定。所以每次規(guī)范更新后我都會(huì)在團(tuán)隊(duì)里同步一次確保每個(gè)人都知道變化點(diǎn)。同時(shí)我會(huì)在渲染管線里加入檢查機(jī)制對(duì)不符合規(guī)范的源文件給出警告幫助大家在提交前發(fā)現(xiàn)問(wèn)題。6.4 從圖表設(shè)計(jì)到信息設(shè)計(jì)的思維躍遷最后想聊一個(gè)更宏觀的話題。diagram-design 表面上是在講圖表但底層其實(shí)是一套信息設(shè)計(jì)的思維方式。圖表只是信息的一種載體同樣的思維方式可以用在文檔結(jié)構(gòu)、演示文稿、數(shù)據(jù)看板、甚至代碼注釋上。核心都是先理清信息結(jié)構(gòu)再選擇表達(dá)形式最后統(tǒng)一視覺(jué)語(yǔ)言。我自己的轉(zhuǎn)變發(fā)生在一次技術(shù)方案評(píng)審上。當(dāng)時(shí)我準(zhǔn)備了一張非常詳細(xì)的架構(gòu)圖自認(rèn)為畫(huà)得很用心。但評(píng)審時(shí)一位資深同事說(shuō)“你這張圖信息很全但我看完不知道重點(diǎn)在哪。”這句話點(diǎn)醒了我圖表的目的是傳遞信息不是展示信息。信息全不等于信息有效重點(diǎn)突出才是關(guān)鍵。從那以后我畫(huà)圖前會(huì)先問(wèn)自己三個(gè)問(wèn)題這張圖要回答什么問(wèn)題讀者最需要看到什么哪些信息可以放到圖外這三個(gè)問(wèn)題想清楚了圖自然就清晰了。這個(gè)思維方式比任何工具和規(guī)范都重要。7. 我個(gè)人的實(shí)操體會(huì)與幾個(gè)實(shí)用建議聊了這么多最后分享幾個(gè)我在實(shí)際項(xiàng)目里總結(jié)的小建議都是踩坑之后覺(jué)得真正有用的。第一個(gè)建議先畫(huà)草圖再寫源文件。不要一上來(lái)就寫DSL先用紙筆或白板把邏輯結(jié)構(gòu)畫(huà)出來(lái)確認(rèn)信息組織沒(méi)問(wèn)題了再轉(zhuǎn)成源文件。這樣能避免在源文件里反復(fù)調(diào)整結(jié)構(gòu)效率更高。第二個(gè)建議建立圖表模板庫(kù)。把常見(jiàn)的圖表類型做成模板比如三層架構(gòu)模板、流程圖模板、時(shí)序圖模板。新圖表從模板開(kāi)始改比從零開(kāi)始快得多也更容易保持風(fēng)格一致。第三個(gè)建議定期清理廢棄圖表。圖表庫(kù)用久了會(huì)積累很多不再使用的圖表。這些廢棄圖表不僅占地方還會(huì)干擾查找。建議每季度清理一次把確認(rèn)不再使用的圖表歸檔或刪除。第四個(gè)建議圖表命名要包含業(yè)務(wù)域和用途。比如“order-system-architecture”“user-registration-flow”這樣在文件列表里一眼就能找到需要的圖表。避免用“圖1”“新建圖表”這種無(wú)意義命名。第五個(gè)建議給圖表加元數(shù)據(jù)。在源文件頭部加上作者、創(chuàng)建時(shí)間、最后修改時(shí)間、用途說(shuō)明等元信息。這些信息在團(tuán)隊(duì)協(xié)作和長(zhǎng)期維護(hù)時(shí)非常有用能省去很多“這張圖是干嘛的”的溝通成本。第六個(gè)建議不要追求一次完美。圖表是迭代出來(lái)的第一版能表達(dá)清楚邏輯就行樣式和細(xì)節(jié)可以后續(xù)優(yōu)化。我見(jiàn)過(guò)太多人因?yàn)榧m結(jié)樣式而遲遲不輸出第一版結(jié)果耽誤了整體進(jìn)度。先完成再完美這個(gè)原則在圖表設(shè)計(jì)上同樣適用。第七個(gè)建議多看優(yōu)秀圖表建立審美直覺(jué)。技術(shù)圖表也有審美好的圖表讓人一看就懂差的圖表讓人越看越糊涂。平時(shí)多留意優(yōu)秀的技術(shù)文檔、架構(gòu)圖、流程圖分析它們?yōu)槭裁辞逦蜁?huì)形成自己的判斷力。這種直覺(jué)比任何規(guī)范都管用。