iT邦幫忙

2026 iThome 鐵人賽

0

今天處理一個很實際的問題:怎麼知道自己「走完了」?

先講一個很多人踩過的坑。如果你打開一個專案,跟 AI 說「幫我分析這個專案」,它會做什麼?

它會從資料夾裡第一個檔案開始讀。

這就是為什麼你會漏掉半個系統。

縱向:從進入點走,不從目錄走

目錄結構反映的是「檔案怎麼擺」,不是「系統怎麼跑」。而在十五年的系統裡,這兩件事差距大到不可思議。

更關鍵的是:讀完所有檔案,不等於走過所有流程。

你可以把每支程式都讀一遍,然後對每支分別產出說明。但那樣得到的是一堆零件說明書,不是「系統怎麼運作」。使用者從按下按鈕到資料進資料庫,中間可能跨了八支程式、兩支預存程序、一個觸發器。這條路徑不會出現在任何單一檔案的說明裡。

所以要從進入點走。而進入點有兩類,大部分人只想到一半:外生進入點(外部訊號觸發):UI 頁面、API 端點、CLI、檔案輸入、webhook。內生進入點(系統自己的非同步訊號觸發):訊息佇列的消費者、事件處理器、檔案監看、排程作業。

外生的看得見——有畫面、有網址、有人會去點。內生的才是舊系統真正的地雷區:沒有畫面、不在主要程式目錄下、可能是個獨立的排程專案、寫的人已經離職,而且它會改資料。我看過的遷移案裡,上線後爆掉的原因有相當比例是「有一個沒人記得的排程,在新系統裡沒有對應的東西」。

走到哪裡停

從進入點往下遞迴,走到四類終點之一:

終點 例子 處理
真葉節點 純計算、直接回傳 停止
成環 A→B→A 把環收縮成一個節點,環本身記為耦合發現
外部匯 寫外部資料庫、呼叫別隊的 API 停止,記下契約
非同步交棒 發訊息、入佇列、發事件、丟檔案 停止這條流,記下通道

兩條規則要強調。

一、只遞迴進「自己的程式」。 外部相依當黑箱,記下契約就好。不然你會花三天讀 ORM 的原始碼,而那對理解業務毫無幫助。

二、要含動態邊。 依賴注入、反射、事件、HTTP、訊息。這些「類別 A 依賴類別 B」的靜態分析看不到的邊,都要納入。舊系統裡透過設定檔決定要呼叫哪個實作的情況非常常見,靜態工具會直接斷在那裡。

非同步縫合:不做會還原出兩個半個 use case

第四類終點是最關鍵、也最多人漏掉的。

當一條流程走到「發出一則訊息」的時候,這條流結束了。但系統的流程沒有結束。一定有某個接收端把它接回去繼續處理。

所以每一個「發訊息」的終點,都要去比對通道的身分(topic 名、佇列名、事件型別、檔案命名規則),把它連到對應的內生進入點。

不做會怎樣?

你會還原出兩個半個 use case。

前半段是「使用者送出,系統寫入,發出一則事件」。看起來完整,其實斷在半路。後半段是「收到事件,扣庫存、發通知、更新報表」。看起來也完整,但你不知道它從哪裡來。兩份文件都自我一致,合起來卻拼不出真正的業務流程。 而且很難察覺,因為兩邊看起來都沒問題。縫合的過程還會順便撈到兩種發現:

  • 有發送端沒有接收端 → 訊息掉進黑洞,可能某個功能早就壞了
  • 有接收端沒有發送端 → 這段是死碼

這兩種孤兒通常都很有價值,而且只有做了縫合才會浮出來。

橫向:七觀點

縱向走完,還是不夠。

因為有一整類的事實,它不在任何一條執行路徑上:

  • 核心服務沒有設定自動擴展
  • 某組金鑰被提交進了版控
  • 分散式追蹤在某個環節斷掉了
  • 連線池的設定在正式環境和測試環境不一致

你把每支程式都讀完、每條切片都走完,也不會有任何一個時刻讓你「發現」這些事。因為它們不是某段程式在做的事,而是整個系統呈現出來的性質。補這一塊的方法是換一組問法。不問「這支程式在做什麼」,改問「這個系統在某個面向上是什麼樣子」。

我用 Rozanski & Woods 的七觀點,每個配一句白話提問:

觀點 一句話提問
功能 它到底做什麼?對外介面有哪些?
資訊 它知道什麼?資料歸誰所有?是不是全部共用一個資料庫?
並行 負載上來怎麼動?鎖在哪?重複執行會不會出事?
開發 它怎麼被修改?分層與相依方向?技術債在哪?
部署 跑在哪裡?環境、拓樸、機敏資料怎麼管?
維運 壞掉的時候看得到嗎?日誌、健康檢查、可觀測性?
安全 會怎麼被攻破?驗證授權、注入、信任邊界?

實務上我會為每個觀點派一個獨立的分析,各自帶著精確的範圍和該找的證據。

而且它們互相不看結論。因為錨定效應。如果第一份報告寫了「這個系統的權限模型是 RBAC」,後面六個會傾向用那個框架去解釋自己看到的東西,即使證據不太支持。

(我看過一個案子實際用這七個觀點做了一份完整的舊系統理解報告,作為後續回顧的判準來源。那份報告的價值不在於它多完整,在於它讓「我們對這個系統的理解」變成一份可以被檢驗的東西。)

跨觀點反覆出現的,才是結構事實

七份報告拿到手,最有價值的動作不是把它們串起來,而是找出同一件事被幾個不同觀點各自撞見。舉例:

  • 資訊觀點說:「訂單和庫存共用同一個資料庫,資料所有權不清楚」
  • 開發觀點說:「這兩個模組互相 import,相依是雙向的」
  • 並行觀點說:「有一支長交易會同時鎖住兩張表」

三個觀點各自獨立分析,用不同的語言、從不同角度,講的是同一件事:**這兩個模組其實沒有分開。**當一件事被三個觀點各自撞見,它就不是某份報告的過度解讀,而是系統真正的結構事實。

反過來說,只有一個觀點提到、其他六個都沒撞到的發現,我會給比較低的權重。

https://ithelp.ithome.com.tw/upload/images/20261101/20178262XrKZBUl1QX.png

涵蓋率記帳:沒有分母就沒有涵蓋率

最後講記帳,這是我後來才加、但覺得應該一開始就要有的東西。做法很簡單:開工前先清點所有檔案數和函式數,當作分母。

然後每走完一條切片,把涉及的檔案和函式標記為「已入案」。整個流程跑完,每一個都必須是兩種狀態之一:

  1. 已入案(歸屬於某條切片或某個觀點)
  2. 不可達/死碼(而且要附證據)

沒有第三種。 不能有「還沒看」的東西默默留在那裡。為什麼要這麼囉唆?因為沒有分母的話,「我分析完了」這句話沒有任何意義。它只是一種感覺。有了分母,它就變成一個可以被檢查的數字:目前入案 847 個函式,總共 862 個,還有 15 個沒著落,這 15 個是哪些。

但結構涵蓋會給你假的 100%

這一段是我認為整個 Part 5 最反直覺的部分。

「每個檔案都被分派給某個人分析過」,不等於「每個危險的行為都被查過」。

一個檔案可以完整地入案了。某份報告盤點過它、寫進了結論、算進了涵蓋率。但從頭到尾,沒有任何人查過它的權限設定、沒有人查過它會不會把敏感資料寫進日誌、沒有人查過它的狀態機是不是漏了某個分支。

因為那些人的任務是「分析這個檔案在做什麼」,不是「檢查這個檔案的授權」。一句話:

危險的東西是行為性的,不是結構性的。
而結構涵蓋只量結構。

所以要另外立一份清單,用屬性提問而不是檔案清點的方式查:

維度 要檢查每一個⋯
授權面 對外端點 → 它的驗證授權是什麼?有沒有沒保護的?
外部匯契約 外部呼叫 → 契約是什麼,以及誰可以呼叫它
狀態完整性 狀態機/分派 → 每個狀態都有分支嗎?
資料曝露 把物件丟進日誌的地方 → 會不會洩漏個資或憑證?
設定生效 承重的設定值 → 缺了會怎樣?設錯會怎樣?
併發安全 共享狀態 → 初始化和存取有沒有競態?

這些問題不會在「每個檔案有沒有人看」裡出現。 它們只會在「每個對外端點的授權我查了嗎」這種逐屬性提問裡出現。

而這剛好呼應 Day 30 講的:任何單一聚合指標都會騙你。 檔案涵蓋率就是一個聚合指標,而它丟掉的資訊,正是最危險的那一塊。

而還有一層,是屬性提問也補不到的

上面那張屬性清單能補「行為性」的缺口。但把整件事拉高一層看,會發現漏的東西還更多。

我後來用一道階梯來檢查自己走到哪裡了。它不是流程——不必照順序走,實務上高度交錯。而是一組必須被涵蓋的層次:

層 復原什麼 靠什麼
⑥ 現代化——重寫或遷移 以下面五層為錨
⑤ 理論——為什麼,以及跟真實世界怎麼對應 只能靠人
④ 約束——欄位長度、Y/N、民國年這些隱性規則 實測 + 人
③ 架構——模組邊界、資料流、接縫在哪 切片 + 觀點
② 領域——這個系統的語言與概念 切片 + 觀點
① 需求——它實際上替真實世界處理了什麼事務 切片 + 觀點

現在把前面那個涵蓋率記帳放進來對照,問題就很清楚了:

縱向切片 × 橫向觀點 —— 掃得到 ①②③
實測(Day 32 那些手法)—— 補得到 ④
而 ⑤ 只能靠人,掃不出來。

**所以「涵蓋率 862/862」量到的是 ①②③ 的完整度,它對 ④⑤ 一個字都沒說。**這就是「假的 100%」真正的形狀。不只是「行為性 vs 結構性」,是整整兩層根本不在那個分母裡。

而這道階梯最反直覺的一點是:

真正的技術工作(⑥)在最上層、也最後做。下面五級全是理論工作。

把預算和時程幾乎全砸在 ⑥、把 ①~⑤ 當成「開發過程中順便就懂了」的專案。那就是 Day 01 那個案子。它花了四個月,最後終於把 ①②③ 做出來了(那 149 份 Use Case),然後就沒有專案可以用它了。

(這道階梯也順帶回答了 Day 36 留下的那個問題:Naur 說「僅憑文件重建理論嚴格不可能」。他說的是 ⑤。而 ①②③ 可以逆向,④ 可以實測,只有 ⑤ 需要那個「與持有理論的人密切接觸」。分清楚這件事,才知道逆向工程到底能買到什麼、買不到什麼。)

小結

  • 從進入點走,不從目錄走;而且外生、內生兩類都要
  • 遞迴到四類終點;只進自己的程式;含動態邊
  • 非同步縫合:不做會還原出兩個半個 use case,而且兩邊看起來都沒問題
  • 七觀點補「不在任何呼叫路徑上」的突現性質;各自獨立分析避免錨定
  • 跨觀點反覆出現的才是結構事實
  • 涵蓋率要有分母,每個檔案/函式只有兩種狀態
  • 但結構涵蓋會給你假的 100%——危險的東西是行為性的,要靠屬性提問
  • 而更根本的是那道階梯:切片與觀點掃得到需求、領域、架構,實測補得到約束,而「理論」那一層只能靠人

明天用一篇講完五個地雷。

參考文獻

  1. Rozanski, N., & Woods, E.(2011)。Software Systems Architecture: Working with Stakeholders Using Viewpoints and Perspectives(2nd ed.)。Addison-Wesley。ISBN 978-0-321-71833-4。
    — 本文的七個觀點(功能、資訊、並行、開發、部署、維運、安全)出自此書。
    要注意版次:第 1 版(2005,ISBN 0-321-11229-6)只有六個觀點,「Context(脈絡)」是第 2 版才加入的。
    本文為了扣合舊系統逆向的實務,把「Context」併入功能觀點的提問裡,另外把該書列為橫切「perspectives」的安全提到觀點層級。這是我的改寫,不是原書的分法。
  2. Tversky, A., & Kahneman, D.(1974)。Judgment under Uncertainty: Heuristics and Biases。Science, 185(4157), 1124–1131。
    — 文中「各觀點互相不看結論,避免錨定」的理由出自這裡(anchoring)。這是心理學上的經典結果,不是我對 AI 行為的觀察;把它套用到「多個代理互看報告」是我的推論,目前沒有量測支持。
  3. 該書另有一組與觀點正交的「perspectives」(安全、效能與擴充性、可用性與韌性、演進性等),用來橫切檢視所有觀點。本文沒有展開這一組,但它跟後面講「證據等級」那一篇是很好的搭配。

上一篇
Day 37 - 逆向工程不是翻譯:忠實翻譯會把缺陷一起搬過去
系列文
綠燈不等於做對:AI 開發的驗收工程 ——從兩個失敗的案子,到驗收交付 共 38 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言