與工程化:軟件工程核心術(shù)語深度解析)
很多做軟件的人都有過這種體驗(yàn)跟同事討論方案時(shí)項(xiàng)目里每個(gè)詞都聽得懂但連成句子就總覺得哪里對不上?!跋到y(tǒng)”到底指什么“工程化”是流程還是工具“上線”和“發(fā)布”是不是一個(gè)意思這些詞不是高級(jí)詞匯卻是在軟件工程里天天都要用的地基詞。尤其是這兩年越來越多的搜索結(jié)果里出現(xiàn)“軟件工程3.0發(fā)展報(bào)告”“工程化的flink代碼”“wms系統(tǒng)”“mes系統(tǒng)”這類說法說明行業(yè)已經(jīng)從“能跑就行”走到“要規(guī)范化、可復(fù)用、可持續(xù)交付”的階段了。這篇術(shù)語庫的“系統(tǒng)與工程化篇”就是把軟件工程里跟系統(tǒng)設(shè)計(jì)、系統(tǒng)邊界、構(gòu)建部署、建模協(xié)作這幾個(gè)方向強(qiáng)相關(guān)的術(shù)語按實(shí)際使用場景整理出來。每個(gè)術(shù)語我會(huì)解釋它到底在說什么、為什么軟件行業(yè)需要它、你跟別人討論時(shí)怎么用才不會(huì)跑偏。適合正在做軟件工程課程設(shè)計(jì)、剛進(jìn)企業(yè)接觸真實(shí)業(yè)務(wù)系統(tǒng)的新人也適合項(xiàng)目里需要跟多個(gè)團(tuán)隊(duì)對齊概念的開發(fā)、測試和產(chǎn)品同學(xué)。這算是一份能當(dāng)工具書翻的詞表但我不打算寫成查字典那種干巴巴的條目而是把每個(gè)詞放到真實(shí)問題里講。1. 從“系統(tǒng)”這個(gè)詞開始講清楚1.1 系統(tǒng)不是“一坨代碼”而是帶目標(biāo)的組織“系統(tǒng)”這個(gè)詞在軟件工程里的含義其實(shí)比大多數(shù)人想象的要嚴(yán)格。它不是“一坨代碼”的禮貌說法而是指為了達(dá)成特定目標(biāo)而組織起來的一組組件集合。重點(diǎn)在“組織”上不在“組件”上。舉個(gè)例子一套電商系統(tǒng)里商品模塊、訂單模塊、支付模塊各管一塊但它們不是各寫各的就能叫系統(tǒng)必須有統(tǒng)一的交互規(guī)則、數(shù)據(jù)格式和異常處理方式才能在面對一個(gè)真實(shí)請求時(shí)像一個(gè)整體那樣工作。這也是很多學(xué)生項(xiàng)目跟企業(yè)系統(tǒng)的差距所在。課程設(shè)計(jì)里常常是“我有一個(gè)商城系統(tǒng)”實(shí)際上就是一個(gè)工程目錄里堆了幾十個(gè)文件功能能跑但模塊之間沒有清晰邊界數(shù)據(jù)格式靠人腦記改一個(gè)地方崩三個(gè)地方。這種代碼量再大也不足以被稱為系統(tǒng)因?yàn)樗鄙僮詈诵牡臇|西對組件之間關(guān)系的刻意設(shè)計(jì)。所以當(dāng)你聽到別人說“這個(gè)系統(tǒng)的架構(gòu)有問題”時(shí)他的潛臺(tái)詞往往不是“代碼寫錯(cuò)了”而是“組件之間的組織方式不合理”。這完全是兩個(gè)層面的問題。代碼層面的問題容易改組織層面的問題往往要?jiǎng)咏Y(jié)構(gòu)。1.2 子系統(tǒng)、模塊、組件粒度不同作用不同軟件工程的術(shù)語里子系統(tǒng)、模塊、組件這幾個(gè)詞經(jīng)常被混用但粒度是有差別的。子系統(tǒng)是系統(tǒng)內(nèi)部最大的功能劃分通??梢元?dú)立運(yùn)行比如電商系統(tǒng)里的訂單子系統(tǒng)、庫存子系統(tǒng)。模塊是子系統(tǒng)內(nèi)部的構(gòu)成單元比如訂單子系統(tǒng)里的價(jià)格計(jì)算模塊。組件則更底層是可以跨模塊復(fù)用的技術(shù)單元比如一個(gè)日志組件、一個(gè)權(quán)限校驗(yàn)組件。理解粒度差異很重要因?yàn)榱6葲Q定了你在哪個(gè)層面做決策。討論子系統(tǒng)時(shí)你關(guān)注的是業(yè)務(wù)邊界和交互方式。討論模塊時(shí)你關(guān)注的是職責(zé)劃分和依賴方向。討論組件時(shí)你關(guān)注的是接口穩(wěn)定性和復(fù)用價(jià)值。很多團(tuán)隊(duì)開會(huì)扯皮本質(zhì)上就是“有人在講組件層面的細(xì)節(jié)有人覺得是在討論子系統(tǒng)層面的方向”話題根本不在一個(gè)平面。實(shí)際工作中我判斷一個(gè)團(tuán)隊(duì)成熟度有一個(gè)土辦法看他們寫文檔或者畫圖時(shí)會(huì)不會(huì)刻意區(qū)分“系統(tǒng)—子系統(tǒng)—模塊—組件”這個(gè)層次。有些團(tuán)隊(duì)畫一張大圖里面既有業(yè)務(wù)邊界又有類名看似全面其實(shí)信息極度混亂。分層是為了讓不同角色看到不同細(xì)節(jié)不是為了讓圖更好看。1.3 最小系統(tǒng)從嵌入式世界學(xué)到的邊界思維“最小系統(tǒng)”這個(gè)詞最早是硬件領(lǐng)域的概念典型就是stm32f103c8t6最小系統(tǒng)板。一塊單片機(jī)要能跑起來不是把芯片焊上就行必須滿足幾個(gè)基本條件正常的電源供電、外部或內(nèi)部時(shí)鐘、復(fù)位電路、啟動(dòng)方式配置。缺了任何一樣芯片就處于不工作狀態(tài)這就是“最小系統(tǒng)”的含義——能讓系統(tǒng)運(yùn)轉(zhuǎn)起來的最小硬件集合。軟件工程里同樣有“最小系統(tǒng)”思維。你做一個(gè)新服務(wù)第一個(gè)里程碑不該是“所有功能都實(shí)現(xiàn)了”而應(yīng)該是“服務(wù)能啟動(dòng)、能處理最基本的請求、能對接基礎(chǔ)設(shè)施、能部署到目標(biāo)環(huán)境”。這個(gè)“能讓系統(tǒng)運(yùn)轉(zhuǎn)起來的最小軟件集合”就是軟件層面的最小系統(tǒng)。這個(gè)思維特別有助于拆解復(fù)雜項(xiàng)目。很多人在做軟件工程項(xiàng)目時(shí)不知道怎么規(guī)劃里程碑一想到完整的功能列表就頭大。如果你按照“先搭最小系統(tǒng)再逐層加碼”的思路整個(gè)節(jié)奏會(huì)清晰很多第一步工程骨架能跑能連數(shù)據(jù)庫能返回一個(gè)健康檢查接口第二步加核心業(yè)務(wù)鏈路哪怕只有一條第三步再補(bǔ)全外圍功能和異常處理。每一階段都處于“可運(yùn)行”狀態(tài)測試可以介入風(fēng)險(xiǎn)也分散了。2. 企業(yè)信息系統(tǒng)里的“XX系統(tǒng)”到底在說什么2.1 ERP、WMS、MES、SCM不是名字不同是管的事不同企業(yè)應(yīng)用軟件里有一堆以縮寫命名的系統(tǒng)erp、wms、mes、scm、crm……對新人來說這串名詞簡直像密碼。實(shí)際上它們的區(qū)別是“管理對象不同”和“管理層次不同”。erp是企業(yè)資源計(jì)劃管的是公司層面的資源調(diào)度比如采購計(jì)劃、生產(chǎn)排程、財(cái)務(wù)核算。wms是倉庫管理系統(tǒng)管的是倉庫內(nèi)部的收貨、上架、揀貨、盤點(diǎn)這些操作。mes是制造執(zhí)行系統(tǒng)管的是車間現(xiàn)場的生產(chǎn)過程比如某個(gè)工單在當(dāng)前時(shí)刻執(zhí)行到哪一步、設(shè)備狀態(tài)如何、質(zhì)量數(shù)據(jù)是什么。scm則是供應(yīng)鏈管理視角更廣覆蓋供應(yīng)商、制造商、分銷商之間的協(xié)同。用一個(gè)不太嚴(yán)謹(jǐn)?shù)糜浀念惐萫rp像公司高層的戰(zhàn)略指揮室決定生產(chǎn)什么、備多少料、資金怎么流轉(zhuǎn)wms是倉庫管理員的臺(tái)賬和掃碼槍管貨品在倉庫里的一舉一動(dòng)mes是車間主任的現(xiàn)場管理白板管產(chǎn)線當(dāng)下的執(zhí)行狀態(tài)。系統(tǒng)核心管理對象典型問題ERP企業(yè)資源與計(jì)劃下個(gè)月生產(chǎn)需要多少原材料資金怎么安排WMS倉庫內(nèi)庫存流轉(zhuǎn)這批貨放在哪個(gè)庫位揀貨怎么走最近路徑MES車間現(xiàn)場執(zhí)行當(dāng)前工單做到哪一步設(shè)備是否異常SCM供應(yīng)鏈上下游協(xié)同供應(yīng)商能不能按時(shí)到貨如何調(diào)整采購節(jié)奏這些系統(tǒng)在真實(shí)企業(yè)里經(jīng)常同時(shí)存在并且需要互相傳遞數(shù)據(jù)。所以“系統(tǒng)集成”就成了企業(yè)信息化里繞不開的話題也就是后面要講的接口、消息和數(shù)據(jù)同步。2.2 平臺(tái)化與模塊化用戶在多個(gè)系統(tǒng)里看到“同一個(gè)系統(tǒng)”企業(yè)用了多套系統(tǒng)之后很快會(huì)遇到一個(gè)痛點(diǎn)數(shù)據(jù)不打通流程斷在各套系統(tǒng)之間。比如倉管員在wms里完成了出庫erp里庫存數(shù)卻不會(huì)自己變財(cái)務(wù)就永遠(yuǎn)不知道真實(shí)庫存是多少。為了解決這個(gè)問題企業(yè)開始做“平臺(tái)化”。平臺(tái)化不是再建一個(gè)新系統(tǒng)把所有功能重寫一遍而是搭建一個(gè)統(tǒng)一的技術(shù)基座和數(shù)據(jù)協(xié)議層讓多個(gè)業(yè)務(wù)系統(tǒng)按同一套規(guī)則接入。這引出兩個(gè)術(shù)語平臺(tái)和能力開放。平臺(tái)是基礎(chǔ)服務(wù)和公共能力的集合比如統(tǒng)一認(rèn)證、統(tǒng)一消息中心、統(tǒng)一數(shù)據(jù)字典。接入平臺(tái)之后各業(yè)務(wù)系統(tǒng)不再各自為政地實(shí)現(xiàn)這些公共能力而是調(diào)用平臺(tái)服務(wù)。模塊化則是更細(xì)一層的設(shè)計(jì)理念。在單一系統(tǒng)里功能不再做成一個(gè)巨型不可拆分的整體而是按業(yè)務(wù)域拆成模塊模塊之間通過穩(wěn)定的接口交互。模塊化的最大好處是“可替換性”。某個(gè)模塊做得不好可以在接口不變的情況下重寫內(nèi)部實(shí)現(xiàn)不影響其他模塊。這也是工程化思想在代碼結(jié)構(gòu)上的落地方式。2.3 系統(tǒng)集成接口、消息隊(duì)列與數(shù)據(jù)一致性多系統(tǒng)之間要交互最常見的方式就是接口調(diào)用。a系統(tǒng)需要庫存數(shù)據(jù)調(diào)用b系統(tǒng)暴露的查詢接口。但接口調(diào)用有兩個(gè)天然問題一是對方如果不可用調(diào)用方怎么辦二是如果業(yè)務(wù)鏈路很長跨系統(tǒng)的事務(wù)如何保證。這時(shí)候就出現(xiàn)了一組高頻術(shù)語同步調(diào)用、異步消息、消息隊(duì)列、最終一致性、冪等。同步調(diào)用像打電話必須等對方接聽并說完才能掛簡單直接但耦合高。異步消息像發(fā)微信發(fā)完你就可以干別的對方處理完再通知你耦合低、抗壓能力強(qiáng)。消息隊(duì)列是最常見的異步消息載體a系統(tǒng)把事件寫入隊(duì)列b系統(tǒng)訂閱并處理雙方不需要同時(shí)在線。數(shù)據(jù)一致性這個(gè)術(shù)語特別容易讓人懵。在分布式系統(tǒng)里像單機(jī)數(shù)據(jù)庫那樣的事務(wù)強(qiáng)一致性幾乎不可能做到所以工程上普遍接受“最終一致性”允許短時(shí)間內(nèi)數(shù)據(jù)不同步但經(jīng)過一定時(shí)間后各系統(tǒng)最終會(huì)達(dá)到一致。這需要配合“冪等”來保證——同一個(gè)請求無論收到幾次結(jié)果都一樣。否則你發(fā)了一張100元優(yōu)惠券消費(fèi)者點(diǎn)了兩次領(lǐng)取系統(tǒng)就發(fā)了200元。講這些術(shù)語不是為了讓你去背概念而是為了讓你在公司里聽到“通過消息隊(duì)列解耦”“需要做冪等處理”這類話時(shí)能馬上理解背后為什么這樣做。它不是炫技是解決真實(shí)問題的必要手段。3. 工程化從寫代碼到交付軟件的規(guī)則體系3.1 構(gòu)建、依賴與包管理工程化的第一關(guān)“工程化”這三個(gè)字很多人以為是用了某個(gè)框架就是工程化。實(shí)際上工程化是從你開始認(rèn)真管理“代碼之外的東西”開始的。第一關(guān)就是構(gòu)建和依賴管理。什么叫構(gòu)建簡單說就是把源代碼變成可交付產(chǎn)物的過程。java里有maven打包前端有webpack或vitepython里有打包成wheel或exe的方式。構(gòu)建不只是“編譯一下”還包括依賴收集、資源處理、配置文件生成、產(chǎn)物版本號(hào)標(biāo)記等環(huán)節(jié)。如果你的項(xiàng)目構(gòu)建要靠某個(gè)人在本地手動(dòng)操作那就還沒有工程化。依賴管理是另一個(gè)高頻詞。項(xiàng)目引了第三方庫這個(gè)庫又依賴其他庫版本不一致可能直接導(dǎo)致運(yùn)行異常這就是“依賴地獄”。工程化的做法是用包管理器統(tǒng)一管理依賴比如maven管java依賴npm管前端依賴pip管python依賴。包管理器負(fù)責(zé)鎖定版本、下載依賴、傳遞依賴關(guān)系讓項(xiàng)目在任何機(jī)器上都能復(fù)現(xiàn)同一套依賴環(huán)境。這里我想提一個(gè)典型的問題場景很多人肯定遇到過在windows上跑npm命令結(jié)果報(bào)錯(cuò)“npm : 無法加載文件 c:\program files\nodejs\npm.ps1因?yàn)樵诖讼到y(tǒng)上禁止運(yùn)行腳本”。這個(gè)報(bào)錯(cuò)的本質(zhì)是powershell的執(zhí)行策略默認(rèn)禁止運(yùn)行腳本文件。npm提供的是命令行工具但在powershell里需要通過腳本執(zhí)行于是被攔住了。這個(gè)報(bào)錯(cuò)的解決方案有幾種第一用cmd而不是powershell來跑npm命令第二以管理員身份打開powershell執(zhí)行set-executionpolicy remotesigned把執(zhí)行策略調(diào)整為“允許本地腳本運(yùn)行遠(yuǎn)程腳本要簽名”。我建議先理解再做不要一上來就搜索“如何解除策略”因?yàn)閳?zhí)行策略是windows一項(xiàng)有意的安全機(jī)制你清楚原因再去調(diào)整以后碰到類似問題才能舉一反三。這類問題看起來是環(huán)境問題實(shí)際上就是工程化必須面對的事情你要讓項(xiàng)目在多個(gè)開發(fā)者的多種環(huán)境里都能跑起來。如果連執(zhí)行腳本這樣的基礎(chǔ)事項(xiàng)都不能統(tǒng)一更別提復(fù)雜的部署協(xié)調(diào)了。3.2 環(huán)境、鏡像與部署讓運(yùn)行環(huán)境可復(fù)現(xiàn)工程化的另一堵墻是“環(huán)境問題”。最常見的現(xiàn)象是“我本地跑得好好的怎么一部署就掛了”。本地能跑生產(chǎn)環(huán)境掛了大概率就是環(huán)境不一致操作系統(tǒng)不同、依賴庫版本不同、配置文件不同、數(shù)據(jù)源不同。為了解決這個(gè)問題業(yè)界沉淀出一套術(shù)語體系。開發(fā)環(huán)境、測試環(huán)境、預(yù)發(fā)布環(huán)境、生產(chǎn)環(huán)境這幾種環(huán)境各自對應(yīng)不同的用途。開發(fā)環(huán)境要求快速迭代、調(diào)試方便測試環(huán)境盡量逼近生產(chǎn)環(huán)境才能發(fā)現(xiàn)真實(shí)問題預(yù)發(fā)布環(huán)境用于做發(fā)布前的最終驗(yàn)證生產(chǎn)環(huán)境就是用戶真正在用的那個(gè)。但光區(qū)分環(huán)境還不夠還得讓環(huán)境“可復(fù)現(xiàn)”。這時(shí)候就輪到鏡像這個(gè)概念出場了。一個(gè)系統(tǒng)鏡像就是把操作系統(tǒng)、運(yùn)行時(shí)、依賴庫、應(yīng)用代碼、配置全部打包成一個(gè)不可變文件。裝系統(tǒng)的時(shí)候你做一個(gè)windows鏡像里面裝好了所有常用軟件和設(shè)置以后重裝只需要用這個(gè)鏡像就能得到一模一樣的系統(tǒng)。軟件部署里的容器鏡像也是同一個(gè)思路把“怎么部署”這件充滿不確定性的事固化成一份可復(fù)制的文件。虛擬機(jī)技術(shù)進(jìn)一步放大了這種能力。你在windows上裝vmware或virtualbox再在上面裝一個(gè)ubuntu系統(tǒng)鏡像就擁有一臺(tái)獨(dú)立于宿主機(jī)的虛擬機(jī)。這樣做的好處是操作系統(tǒng)的差異、配置的差異都可以在虛擬化層隔離掉你可以在同一臺(tái)物理機(jī)上體驗(yàn)多個(gè)系統(tǒng)環(huán)境。在部署這個(gè)環(huán)節(jié)現(xiàn)在還有“不可變基礎(chǔ)設(shè)施”的說法意思是運(yùn)行環(huán)境一旦創(chuàng)建就不在原位修改每次都通過重新創(chuàng)建來更新。這樣就沒有“環(huán)境被改得面目全非”的問題部署過程更像“用新鏡像做一次替換”而非“在原機(jī)器上打補(bǔ)丁”。這套思路在企業(yè)級(jí)系統(tǒng)里已經(jīng)非常普遍。3.3 持續(xù)集成、持續(xù)交付與質(zhì)量門禁工程化的引擎持續(xù)集成ci、持續(xù)部署cd、流水線、質(zhì)量門禁這組術(shù)語是現(xiàn)代工程化的核心引擎。持續(xù)集成強(qiáng)調(diào)“頻繁地把代碼合并到主干并且每次合并都自動(dòng)運(yùn)行構(gòu)建和測試”。為什么強(qiáng)調(diào)持續(xù)因?yàn)榧傻某杀倦S著時(shí)間推移會(huì)指數(shù)級(jí)上升分支開發(fā)太久合并時(shí)沖突多、驗(yàn)證難、情緒差。把集成變成高頻動(dòng)作問題就提前暴露、提前解決。持續(xù)交付則是在持續(xù)集成的基礎(chǔ)上讓產(chǎn)物始終處于“可部署狀態(tài)”通過自動(dòng)化流水線把構(gòu)建、測試、部署的步驟串起來。流水線就是一條自動(dòng)化執(zhí)行的流程每一步如果在代碼提交后自動(dòng)觸發(fā)比如代碼上傳到倉庫之后自動(dòng)開始編譯、跑單測、打鏡像、推送到測試環(huán)境只有每一步都通過才會(huì)推進(jìn)到下一階段。質(zhì)量門禁指的是把質(zhì)量規(guī)則嵌進(jìn)流水線。比如測試覆蓋率不得低于某個(gè)閾值、代碼掃描不得出現(xiàn)高危漏洞、構(gòu)建產(chǎn)物必須通過安全檢測。沒達(dá)標(biāo)的代碼連進(jìn)入下一步的資格都沒有。這樣做是把約束前置而不是等上線后人肉檢查。持續(xù)部署在某些團(tuán)隊(duì)里進(jìn)一步自動(dòng)化到“一鍵上線”或“全自動(dòng)上線”。實(shí)際操作里大家還會(huì)搭配發(fā)布策略來控制風(fēng)險(xiǎn)比如藍(lán)綠發(fā)布、金絲雀發(fā)布、灰度發(fā)布。金絲雀發(fā)布這個(gè)說法來源于一個(gè)老典故礦工下礦帶金絲雀進(jìn)去如果空氣有毒金絲雀先倒。用在發(fā)布上就是先讓新版本只對一小部分用戶生效觀察無異常后再放量給全部用戶。灰度發(fā)布和它類似按比例逐步放開流量出現(xiàn)問題能及時(shí)掐斷。4. 建模與文檔類術(shù)語讓軟性認(rèn)知變成硬性共識(shí)4.1 UML與用例圖畫圖不是為了好看是為了對齊軟件工程課程里最早接觸的模型圖大概率就是uml圖。uml是統(tǒng)一建模語言本質(zhì)是一套標(biāo)準(zhǔn)化的圖形語法用來表達(dá)軟件系統(tǒng)的靜態(tài)結(jié)構(gòu)和動(dòng)態(tài)行為。為什么要標(biāo)準(zhǔn)化因?yàn)閳D形化表達(dá)比文字更容易被不同角色快速理解但前提是大家用同一套規(guī)則畫圖否則各畫各的比不畫還亂。用例圖是uml里用來描述系統(tǒng)功能需求的一類圖三要素是參與者、用例和關(guān)系。參與者是和系統(tǒng)交互的外部角色可以是人也可以是另一個(gè)系統(tǒng)。用例是一個(gè)完整的功能目標(biāo)強(qiáng)調(diào)“給參與者帶來什么價(jià)值”。關(guān)系則描述參與者和用例之間、用例和用例之間的聯(lián)系比如“包含”和“擴(kuò)展”兩種關(guān)系。我最想強(qiáng)調(diào)的是“用例視角”。很多人在畫用例圖時(shí)習(xí)慣把用例命名成功能清單比如“保存訂單”“修改庫存”“生成報(bào)表”看起來是一個(gè)個(gè)動(dòng)作但這不是用例的正確打開方式。用例的主體應(yīng)該是用戶目標(biāo)應(yīng)該是“提交訂單”“查詢庫存狀態(tài)”“導(dǎo)出月度報(bào)表”這類從使用者視角看有明確價(jià)值的完整目標(biāo)。如果你畫的用例圖看起來像菜單列表那大概率還沒切換到用例思維。4.2 核心UML圖速覽什么時(shí)候該畫哪種圖uml圖很多但對實(shí)際項(xiàng)目最有存在感的通常是這幾類類圖、時(shí)序圖、狀態(tài)圖、活動(dòng)圖、組件圖。類圖描述系統(tǒng)的靜態(tài)結(jié)構(gòu)展示類、接口、屬性和方法之間的關(guān)聯(lián)。設(shè)計(jì)階段用類圖比較多用來明確數(shù)據(jù)結(jié)構(gòu)和方法歸屬。時(shí)序圖描述對象之間在時(shí)間維度上的交互順序特別適合表達(dá)一個(gè)業(yè)務(wù)場景里多個(gè)模塊怎么協(xié)作。比如“用戶下單”這條鏈路哪些服務(wù)先調(diào)哪些服務(wù)出現(xiàn)異常時(shí)誰來兜底時(shí)序圖能表達(dá)得比文字清楚得多。狀態(tài)圖描述一個(gè)對象在生命周期里可能經(jīng)歷的狀態(tài)以及觸發(fā)狀態(tài)遷移的事件。典型的例子就是訂單狀態(tài)待支付、已支付、已發(fā)貨、已完成、已取消每個(gè)狀態(tài)遷移都由特定事件觸發(fā)。狀態(tài)圖最適合處理“這個(gè)對象在不同條件下行為不同”的場景?;顒?dòng)圖描述業(yè)務(wù)或算法的流程分支類似流程圖但表達(dá)能力更強(qiáng)。它適合梳理復(fù)雜業(yè)務(wù)流程的邏輯順序。組件圖描述系統(tǒng)的物理模塊結(jié)構(gòu)適合表達(dá)子系統(tǒng)或服務(wù)的部署與依賴關(guān)系。模型和圖紙的真實(shí)作用不是讓程序員照著圖敲代碼而是把大家的理解拉到同一基線。所以畫圖的第一準(zhǔn)則永遠(yuǎn)是“這個(gè)圖解決了什么溝通問題”而不是“這個(gè)圖畫得標(biāo)準(zhǔn)不標(biāo)準(zhǔn)”。4.3 文檔資產(chǎn)SRS、SDD、接口文檔與“足夠好”的平衡軟件工程的文檔體系里最常被提到的幾個(gè)縮寫是srs、sdd、api文檔。srs是軟件需求規(guī)格說明集中描述系統(tǒng)要做什么包括功能需求和非功能需求。是需求階段的核心產(chǎn)出也是后續(xù)設(shè)計(jì)、測試的依據(jù)。sdd是軟件設(shè)計(jì)說明描述系統(tǒng)怎么做包括總體架構(gòu)、模塊設(shè)計(jì)、接口設(shè)計(jì)、數(shù)據(jù)庫設(shè)計(jì)。有一個(gè)經(jīng)常被誤解的真相文檔不是寫給流程看的是為了延續(xù)“意圖”。項(xiàng)目做了半年最初的設(shè)計(jì)決策為什么這樣做如果不在文檔里留下記錄后面的人就只能靠猜。猜測成本極高而且極容易把系統(tǒng)帶偏。但敏捷開發(fā)時(shí)代很多團(tuán)隊(duì)完全不做文檔又是一條歧路。敏捷宣言里強(qiáng)調(diào)的是“可用的軟件勝過完備的文檔”注意是勝過不是徹底不要。現(xiàn)實(shí)判斷標(biāo)準(zhǔn)應(yīng)該是這篇文檔有沒有降低團(tuán)隊(duì)協(xié)作的信息損耗如果有就該寫如果只是因?yàn)榱鞒桃蠖鴮懩谴_實(shí)是浪費(fèi)。接口文檔在聯(lián)調(diào)環(huán)節(jié)尤其關(guān)鍵。兩個(gè)系統(tǒng)對接接口的請求參數(shù)、響應(yīng)結(jié)構(gòu)、錯(cuò)誤碼、鑒權(quán)方式如果不寫清楚聯(lián)調(diào)就變成互相猜謎。更麻煩的是接口文檔如果跟實(shí)際代碼不一致比沒有文檔更坑人。所以接口文檔的建設(shè)最好能跟代碼走能自動(dòng)生成就自動(dòng)生成人為維護(hù)的多一份就多一份陳舊的可能。5. 過程與團(tuán)隊(duì)協(xié)作類術(shù)語工程化背后是人的協(xié)同5.1 生命周期與開發(fā)流程模型項(xiàng)目節(jié)奏的框架軟件工程里最基礎(chǔ)的模型是瀑布模型階段清晰需求、設(shè)計(jì)、編碼、測試、維護(hù)每個(gè)階段完成后進(jìn)入下一階段。瀑布模型適合需求穩(wěn)定、變更成本高的項(xiàng)目比如某些大型基礎(chǔ)設(shè)施改造。它的弱點(diǎn)是反饋周期太長需求要全部確定才能開始設(shè)計(jì)設(shè)計(jì)要完成才能開始編碼一旦后期發(fā)現(xiàn)需求理解錯(cuò)了返工成本比較大。后來業(yè)界普遍轉(zhuǎn)向迭代和敏捷。迭代開發(fā)是把項(xiàng)目切成多個(gè)迭代周期每個(gè)周期都產(chǎn)出可運(yùn)行、可反饋的增量而不是等到最后才一次性交付。敏捷則是一套價(jià)值觀和實(shí)踐的組合強(qiáng)調(diào)響應(yīng)變化、持續(xù)交付、跨職能團(tuán)隊(duì)協(xié)作。到落地層面最常見的敏捷實(shí)踐是scrum。scrum里有幾個(gè)被用濫的術(shù)語sprint是固定長度的時(shí)間盒通常一到四周看板是可視化任務(wù)流轉(zhuǎn)的板子用來觀察瓶頸不是用來催進(jìn)度stale meeting是短會(huì)通常叫每日站會(huì)過一下“昨天做了什么、今天打算做什么、有沒有阻塞”。這些實(shí)踐本身不是靈丹妙藥它們的價(jià)值在于推動(dòng)團(tuán)隊(duì)暴露問題和快速調(diào)整??荚?yán)镞€經(jīng)常出現(xiàn)“軟件生命周期”這個(gè)概念別把它理解成“項(xiàng)目從開始到結(jié)束就行”更準(zhǔn)確的理解是軟件系統(tǒng)的全過程不只是開發(fā)和上線還包括上線后的維護(hù)、演化和最終退役。一句口訣這是個(gè)長期陪伴的過程不是一次性工程。5.2 常見角色與職責(zé)邊界架構(gòu)師到底在“架構(gòu)”什么軟件工程里角色術(shù)語很多常見的有產(chǎn)品經(jīng)理、需求分析師、架構(gòu)師、技術(shù)負(fù)責(zé)人、開發(fā)工程師、測試工程師、運(yùn)維工程師、項(xiàng)目經(jīng)理。由于每個(gè)公司對職責(zé)的定義不一樣這些詞在不同組織里含義不完全相同但有共性的部分。架構(gòu)師這個(gè)詞被賦予了太多光環(huán)。實(shí)際工作中架構(gòu)師最核心的職責(zé)是兩件事做技術(shù)決策和維護(hù)決策落地的機(jī)制。所謂技術(shù)決策不是選一個(gè)中間件那么簡單而是在多個(gè)方案之間權(quán)衡成本、風(fēng)險(xiǎn)、團(tuán)隊(duì)能力、未來演進(jìn)方向最后拍板。所謂維護(hù)決策落地的機(jī)制是說決策定了之后還要推動(dòng)大家按決策執(zhí)行否則就是“架構(gòu)是架構(gòu)代碼是代碼”。測試工程師的職責(zé)也在不斷演進(jìn)。傳統(tǒng)觀點(diǎn)是測試人員負(fù)責(zé)“找bug”但更先進(jìn)的理解是測試應(yīng)該是質(zhì)量保障的一部分不只是發(fā)現(xiàn)問題更是通過測試反饋?zhàn)寙栴}早出現(xiàn)、少出現(xiàn)。與之相關(guān)的術(shù)語還有“測試金字塔”底層是大量單元測試中間層是較少的服務(wù)集成測試頂層才是少量的端到端測試。按照這個(gè)比例做測試能讓投入產(chǎn)出比最大化。運(yùn)維工程師這幾年也被devops這個(gè)概念重塑了。devops不是崗位是一套打破開發(fā)與運(yùn)維壁壘的文化和實(shí)踐核心是讓開發(fā)團(tuán)隊(duì)也承擔(dān)一部分運(yùn)維責(zé)任讓運(yùn)維能力前移到開發(fā)階段。5.3 測試與質(zhì)量保障術(shù)語不是越測越穩(wěn)而是設(shè)計(jì)決定質(zhì)量測試類術(shù)語里單元測試是最基礎(chǔ)的一層驗(yàn)證一個(gè)函數(shù)或一個(gè)模塊在小范圍內(nèi)的行為是否符合預(yù)期。集成測試驗(yàn)證多個(gè)模塊組合在一起是否正常工作。系統(tǒng)測試是把系統(tǒng)作為一個(gè)整體做驗(yàn)證看是否符合需求。驗(yàn)收測試則是站在用戶視角確認(rèn)系統(tǒng)是否滿足業(yè)務(wù)訴求。回歸測試是在修改代碼之后重新跑一遍已有的測試用例確保改動(dòng)沒有破壞已有功能。這個(gè)術(shù)語工作中出現(xiàn)頻率極高因?yàn)椤靶迯?fù)一個(gè)bug引入另一個(gè)bug”是常態(tài)。質(zhì)量保障這塊除了測試執(zhí)行還有兩個(gè)常聽到的詞code review和靜態(tài)分析。code review是讓其他開發(fā)者看代碼并提意見目的不只是找bug更是讓團(tuán)隊(duì)對代碼風(fēng)格、設(shè)計(jì)思路、實(shí)現(xiàn)方案有共同認(rèn)知。靜態(tài)分析則是在不運(yùn)行代碼的情況下用工具掃描代碼中的隱患比如空指針風(fēng)險(xiǎn)、資源未釋放、循環(huán)復(fù)雜度太高等相當(dāng)于給代碼加了一道自動(dòng)化體檢。這里要糾正一個(gè)觀念很多人以為測試做得越多系統(tǒng)越穩(wěn)定這是錯(cuò)的。測試只能驗(yàn)證“測過的場景沒有出錯(cuò)”不能證明系統(tǒng)沒有問題。質(zhì)量的核心源頭在設(shè)計(jì)階段。一個(gè)設(shè)計(jì)混亂、依賴糾纏不清、狀態(tài)管理失控的系統(tǒng)無論測試多用力bug仍然防不勝防。所以工程化的關(guān)鍵不是加多少道測試而是讓系統(tǒng)從結(jié)構(gòu)上就具備可控性。測試是質(zhì)量防線設(shè)計(jì)才是質(zhì)量根基。還有一組術(shù)語容易被混淆錯(cuò)誤、缺陷、故障。錯(cuò)誤是人為的缺陷是代碼或系統(tǒng)內(nèi)在的毛病故障是缺陷在特定條件下露出來導(dǎo)致的系統(tǒng)行為異常。三個(gè)詞的區(qū)別有助于更精確地描述問題。比如線上系統(tǒng)突然響應(yīng)慢這叫故障排查發(fā)現(xiàn)某個(gè)函數(shù)空指針這是缺陷因?yàn)槟澄煌聸]有判空這是錯(cuò)誤。把這三個(gè)詞分開復(fù)盤時(shí)就能準(zhǔn)確歸因而不是籠統(tǒng)地說“出bug了”。五組術(shù)語梳理下來可以拆成兩條暗線。第一條是“系統(tǒng)”線從系統(tǒng)概念本身到子系統(tǒng)模塊的粒度再到企業(yè)信息系統(tǒng)、業(yè)務(wù)系統(tǒng)的概念譜系最終落到系統(tǒng)邊界和系統(tǒng)集成。第二條是“工程化”線從構(gòu)建、依賴管理、環(huán)境、鏡像、部署到持續(xù)集成、持續(xù)交付、流水線和質(zhì)量門禁再到建模、文檔和團(tuán)隊(duì)協(xié)作。我在實(shí)際項(xiàng)目里有個(gè)很深的體會(huì)工具和方法論都是顯性的真正決定工程化水平的是隱性共識(shí)——團(tuán)隊(duì)里每個(gè)人對術(shù)語的理解是不是同一種含義。比如“上線”在當(dāng)前團(tuán)隊(duì)里是指“合并到主干”還是“部署到生產(chǎn)環(huán)境”“系統(tǒng)”在方案討論里是指“全部代碼”還是“某個(gè)獨(dú)立服務(wù)”一旦這些詞匯在語義上錯(cuò)位溝通成本會(huì)成倍增長。所以在對齊需求和評(píng)審架構(gòu)時(shí)我經(jīng)常愿意花半小時(shí)先把大家的概念校準(zhǔn)一遍這半小時(shí)遠(yuǎn)比討論過程中反復(fù)澄清要高效得多。這篇術(shù)語庫適合放在手邊當(dāng)成案頭參考當(dāng)你在文檔、會(huì)議、面試或者課程設(shè)計(jì)里遇到這個(gè)術(shù)語拿不準(zhǔn)回來翻一翻對應(yīng)的章節(jié)就好。如果你發(fā)現(xiàn)團(tuán)隊(duì)里經(jīng)常因?yàn)槟硞€(gè)詞吵來吵去那多半不是立場問題是定義問題。先把詞對齊再談方案事情會(huì)順暢很多。