快轉到主要內容
  1. 文章/

從 Change 到真實狀態:如何讓持續迭代的系統收斂,而不是發散

·2 分鐘

1. 問題是從哪裡開始的? #

這次思考的起點,其實不是想整理一套軟體開發方法,而是因為我開始嘗試和 LLM 一起工作。

AI 時代有一個很明顯的變化:產生資訊、整理資訊、修改程式與建立文件的成本大幅下降。以前需要花很多時間才能完成的分析、規格整理或實作,現在可能只需要幾輪對話就能產生一個可用的版本。

這讓「把想法快速變成東西」變得非常容易,但也帶來一個蠻反直覺的問題:當產生資訊的成本接近於零,資訊本身反而開始爆炸。

這也是我開始重新思考 SSoT、Intent、Spec 與 Canon 的原因。

開發一個新的系統或工具時,我很自然會採用 MVP 的方式。

先有一個想法,快速做出雛形,確認它是否真的有用。只要能運作,就拿到真實的專案裡使用。

接著,實際使用會產生新的問題:

  • 某個功能不符合預期
  • 某個需求原本沒有想清楚
  • 某個規則不夠完整
  • 實作方式產生新的限制
  • 使用後發現其實還需要另一個能力

於是,每一個問題又變成下一個 Change。

這個循環一開始非常有效:

MVP 回饋循環:Change → Implement → Use → Feedback,再回到下一個 Change

但當系統越來越大,問題就開始出現了。

舊問題還沒處理完,新問題又不斷冒出來。

最後 backlog 越來越長,功能越來越多,系統卻沒有變得更一致。

這時候我心裡冒出一個很直覺的疑問:

是不是系統已經開始發散了?


2. 問題可能不是 Iteration,而是 Change 被扁平化了 #

仔細觀察後我發現,問題不一定出在「持續迭代」。

真正的問題可能是:

我把所有 Change 都當成了同一種東西。

例如:

「Plugin 要支援 hot reload。」

這可能是一個新的 Intent。

但:

「hot reload 在某種情況下會失敗。」

可能只是 Implementation 的問題。

又或者:

「原本根本沒有定義 hot reload 失敗時應該發生什麼。」

這其實是 Spec 的問題。

再例如:

「已經定義了失敗行為,但測試沒有驗證。」

這又是 Verification 的問題。

如果這些東西最後全部只是變成:

TODO: 修掉 hot reload

那麼不同層級的問題就被壓扁成同一種工作項目。

系統失去的不是工作管理能力,而是語義上的分類能力

在和 LLM 協作的情境下,這個問題會更明顯。

因為 LLM 很擅長根據一個 Change 立刻生出下一個 Change:一個想法可以迅速變成規格,一個規格可以迅速變成程式,一個問題又可以迅速產生另一個修正方案。

速度本身不是問題。問題是,如果沒有一個清楚的結構去吸收這些產出,那我只是把原本需要幾天才累積得出來的資訊混亂,壓縮成幾個小時。

AI 降低了資訊產生的成本,也同時提高了管理資訊結構的需求。


3. 從 Intent 開始分層 #

因此,我開始把系統中的資訊分成不同層次。

最上層是 Vision。

Vision 描述的是:

這個系統存在的目的,以及希望最終帶來什麼效果。

例如做一個遊戲,不只是「我要做一個遊戲」,而可能是:

希望打造一個讓玩家透過探索持續獲得驚喜的遊戲。

在這個 Vision 之下,才會產生不同的 Intent。

Intent 描述的是:

基於這個 Vision,我現在想解決什麼問題,或想增加什麼能力?

Intent 再往下被具體化成 Spec。

Spec 開始回答:

在什麼條件下,系統應該產生什麼可觀察、可驗證的結果?

接著才是 Implementation:

如何實際實現這些規格?

最後透過 Verification:

怎麼確認 Implementation 真的符合 Spec?

因此可以得到一條基本鏈:

五層語義鏈:Vision → Intent → Spec → Implementation → Verification

這條鏈並不是單純的開發流程,而是不同資訊的語義層級。


4. 但這不是一棵單純的樹 #

我一開始也把這個模型想成樹狀結構,但實際的系統演化並沒有這麼簡單:

想像中的樹狀結構 vs 實際上有層級的網狀結構

一個 Intent 可能對應多個 Spec。

一個 Spec 也可能同時支援多個 Intent。

一個 Implementation 可能實現多個 Spec。

Verification 發現的問題,也可能一路往上影響 Spec、Intent,甚至重新改變 Vision。

所以更精確的模型其實是:

有層級的網狀結構。

「層級」負責描述資訊的抽象程度。

「網狀關係」則描述這些資訊彼此之間的依賴與支援關係。

因此真正重要的問題不再只是:

這個東西在樹上的哪個位置?

而是:

這個 Change 應該落在哪一個語義層?它改變之後,哪些相關資訊需要重新驗證?


5. SSoT 的意義開始改變 #

這也讓 SSoT 有了另一種更深的意義。

SSoT 不只是:

「到底哪一份文件是真的?」

更重要的是:

對於每一種資訊,到底哪一個地方才是它的權威來源?

如果沒有這個定義,那麼 Vision、Intent、Spec、Implementation、Verification 可能全部混在一起。

當系統收到一個 Change 時,根本不知道應該修改什麼。

因此,SSoT 的價值之一,就是建立這些資訊之間的邊界與權威性。


6. Canon:系統目前承認的真實狀態 #

這裡我想引入另一個概念:Canon。

Canon 在這裡指的是:

系統目前正式承認、具有權威性的真實狀態與規則。

它不是歷史紀錄,也不是所有曾經發生過的 Change。

它更接近:

「截至目前,這個系統到底認定什麼是真的?」

例如一開始 Spec 認為:

使用者登入失敗三次後必須鎖定帳號。

後來實際使用發現這個規則造成問題。

經過討論後,決定改成五次。

那麼「五次」成為新的 Canon。

舊的「三次」可以存在於歷史紀錄中,但它不再是目前系統的權威狀態。

因此:

History 記錄系統曾經是什麼。

Canon 定義系統現在認為是什麼。

這兩者需要被區分。


7. Iteration 不只是產生 Change,還需要吸收 Change #

這帶來一個重要的概念:Absorption。

Iteration 的目的不應該只是:

發現問題 → 新增工作 → 修掉問題

還應該包含:

發現問題 → 判斷問題屬於哪一層 → 更新正確層級的知識 → 重新建立一致狀態

這就是 Change 的吸收。

例如:

Implementation 發現某個行為不符合預期。

首先不是立刻新增一個 TODO。

而是先問:

這到底是哪一層的問題?

如果是程式寫錯,就修改 Implementation。

如果是規格定義錯,就修改 Spec。

如果發現原本想解決的問題根本不是這個,就重新檢視 Intent。

如果甚至發現整個系統存在的目的都需要重新思考,那麼就可能一路回到 Vision。

Absorption 的核心不是「把問題修掉」,而是把這次 iteration 得到的新知識,正式納入系統的權威狀態。


8. 因此,真正的收斂機制可能是這個 #

我原本看到的是:

Iteration → 越做越多 → 越來越複雜

但更完整的循環應該是:

Change 的收斂循環:Change → Classification → 找到正確的語義層 → 修改該層 → Verification → Absorption → 更新 Canon → 下一輪 Iteration

因此:

Iteration 本身不會讓系統收斂。

真正讓系統收斂的是:

每次 Iteration 產生的 Change,都能被正確分類、吸收,並重新建立一個一致的 Canon。


9. 回頭看我自己的一個 Plugin 開發經驗 #

這裡可以回到我自己開發一個 Plugin 的經驗。

這個 Plugin 的開發方式很接近 MVP:我先有一個想法,就快速實作一個可用的雛形,然後放進真實專案裡使用。

使用的過程中,不斷產生新的問題與想法。每個問題又成為下一個 Change,透過一次又一次的小型 iteration 持續改善它。

這種方式在早期非常有效,因為我可以用很低的成本驗證想法,而不需要一開始就把整個系統設計完整。

但當這個 Plugin 被使用得越來越多,Change 也開始大量累積,原本快速迭代的優勢逐漸變成負擔。

這時候回頭看,我才理解為什麼一個透過大量 Intent 快速堆疊出來的 Plugin,最後會開始發散。

問題不一定是 MVP 錯了。

也不一定是快速 Iteration 錯了。

甚至也不一定是技術債太多。

更深一層的問題可能是:

所有 Feedback 最後都被轉換成下一個 Change,卻沒有被重新分類並吸收到系統的知識結構中。

於是:

  • 新 Intent 不斷增加
  • Spec 問題變成 TODO
  • Implementation Bug 變成 TODO
  • Verification Gap 變成 TODO
  • 設計決策也變成 TODO

最後所有東西都進入同一個 backlog。

系統就開始失去方向。

這就是「發散」。


10. 這些概念其實不是新的 #

寫到這裡,我自己也冒出一個問題:這些東西是不是早就有人討論過了?

答案是肯定的。

我整理出來的這個模型,並不是要重新發明一套軟體工程理論。相反地,它和許多既有的軟體工程領域有很深的關係,只是這些概念通常分散在不同的學科與實務方法裡。

例如,Requirements Engineering 長期就在處理需求的分析、規格化、驗證,以及需求變更與 Traceability。它關心的其中一個核心問題,就是一個高層需求如何一路對應到規格、設計、實作與測試。

這和前面說的「有層級的網狀結構」非常接近。

另一個相關領域是 Software Architecture。Architecture Decision Record(ADR)則進一步記錄「為什麼系統會變成現在這個樣子」,而不只是記錄目前的程式碼。這和 Canon 想表達的「目前被系統承認的真實狀態」也有明顯的關聯。

此外,Configuration Management、Change Management、Verification & Validation,以及 Knowledge Management,也都在不同角度處理同一個大問題:

當系統持續改變時,怎麼知道它現在到底是什麼?為什麼會變成這樣?改變之後,哪些東西需要重新驗證?

因此,Vision、Intent、Spec、Implementation、Verification、Traceability、ADR、Change Management 等概念,並不是彼此孤立的東西。

這篇文章真正想做的,不是宣稱提出一套新的方法,而是從我自己的 Plugin 開發經驗出發,把這些分散的概念重新放在同一張圖上。

尤其值得注意的是,本文使用的 Canon 與 Absorption 並不一定等同於某個既有的標準術語。它們比較像是我目前用來描述這個模型的暫定語言:Canon 用來表示「系統目前正式承認的真實狀態」,Absorption 則用來表示「把 iteration 得到的新知識正式納入這個狀態」的過程。

因此,下一步真正值得研究的,反而不是「這是不是一個全新的理論」,而是:

這個模型和既有 Software Engineering 方法到底重疊在哪裡?又在哪些地方提供了不同的觀點?

11. 最後重新理解 SSoT #

因此,SSoT 可能不只是「Single Source of Truth」這句話本身。

更重要的問題是:

什麼資訊應該由什麼東西定義?

什麼資訊目前才具有權威性?

當 Change 發生時,它應該改變哪一個層級?

改變之後,哪些東西需要重新驗證?

這次 iteration 得到的新知識,最後如何被吸收到 Canon?

如果這些問題沒有答案,那麼即使每一份文件都有一個「SSoT」,整個系統仍然可能發散。

反過來,如果這些關係被清楚定義,SSoT 就不只是文件管理技巧,而開始變成一種管理系統知識與演化的方法


結語:真正想控制的不是 Change,而是 Truth 的演化 #

系統不可能停止變化。

新的需求會出現,新的問題會出現,Implementation 會失敗,使用者會提供新的 Feedback。

因此,「不要讓系統改變」不是收斂。

真正的收斂是:

允許系統持續改變,但每一次改變都能被正確理解、分類、驗證,最後成為新的真實狀態。

所以真正需要管理的,也許不是 Change 本身。

而是:

Change 最後如何改變系統所承認的 Truth。

這可能才是 SSoT、Canon、Intent、Spec 與 Verification 真正開始串起來的地方。