在軟體開發中,我們常聽到「可演進架構」(Evolutionary Architecture)這個詞。簡單來說,這類架構的核心假設是:變更是常態而非意外。因此,衡量一個架構是否成功的標準,不在於它是否「不會變」,而是在於:當業務需求改變時,正確的團隊是否能憑藉「適量的上下文」就完成變更,而不需要理解整個系統的所有細節。
這種能力被稱為「變更局部性」(Change Locality)。
什麼是變更局部性?
變更局部性是指當一個業務功能需要修改時,負責該功能的團隊能夠在不重建整個系統認知的情況下,回答三個關鍵問題:這裡可以改什麼?有哪些合約(Contract)保護著鄰近的功能?如何證明這次變更在生產環境中是安全的?
理想狀態下,變更所需的認知負荷(Cognitive Load)應該與變更的規模成正比。如果你只是想修改一個地址欄位的文字,卻需要理解整個物流配送模型,這就代表局部性很弱,架構出現了問題。
邊界偏移:當局部性失效的時刻
在系統剛建立時,我們通常會根據當時的業務邏輯劃分邊界(Boundary)。例如,一個電商系統的「結帳模組」負責處理訂單確認與地址設定。起初,修改地址很簡單,只要結帳團隊改好程式碼並測試即可。
但隨著業務成長,情況會變得複雜: 倉庫有了截單時間(Cutoff time)。 風控團隊加入了反詐騙規則(Fraud rules)。 物流合作夥伴對地址格式有特定要求。 客服團隊承諾客戶在特定時間內可修改地址。
雖然「修改地址」的請求依然進入結帳模組,但決定「能否修改」的權限已經分散到了倉庫、風控、物流與客服團隊手中。這就是所謂的「邊界偏移」(Boundary Drift)。
邊界偏移是指:系統在文件或程式碼結構上的邊界依然存在,但現實中業務決策的路徑已經移走了。結帳團隊雖然名義上擁有這個功能,但他們不再擁有決定變更是否安全的完整資訊。
如何識別邊界偏移?
對於 Junior 工程師或團隊領導者來說,最明顯的信號就是「認知負荷過重」。當你發現以下現象時,請警覺邊界可能已經偏移:
一個看似簡單的小功能,在實作時發現牽涉到三個以上所有權不明的系統。 事故復盤(Post-mortem)時發現,修復問題竟然依賴於某個資深工程師對多年前隱藏依賴的記憶。 新進成員上手時間極長,因為安全地修改程式碼所需的知識不在文件或測試中,而是在某些人的腦袋裡。 一個只有 10 行程式碼的 Pull Request,卻引發了 50 條評論,因為審閱者對「正確行為」沒有共識。
這類問題通常是社會技術性(Sociotechnical)的,不僅是技術問題,還涉及團隊分工、營運流程與人員記憶。
恢復局部性的三項策略
當發現邊界偏移導致開發效率下降時,架構師可以透過以下三種手段來恢復局部性:
重新分配重複機制(Redistribute Repeated Mechanics) 將純技術的重複操作(例如:計算截單時間的邏輯、通知發送機制、基礎設施設定)抽離到平台層或共享服務中。但要注意,只能移動「機制」,不能將「業務政策」移入平台,否則會導致業務邏輯被掩蓋在平台底層,增加認知負擔。
顯露核心政策(Expose Essential Policy) 讓負責變更的團隊能清晰地看到限制條件。例如,結帳團隊不需要擁有倉庫的權限,但必須透過 API 合約、合約測試(Contract Tests)或儀表板,能明確知道「訂單是否已打包」或「風控是否攔截」。目標是讓決定安全性的因素變得透明且可讀。
演練異常路徑(Rehearse Exception Paths) 重新設計後,必須測試那些曾經需要「專家協調」才能解決的極端案例。如果處理一個地址修改的異常情況,依然得依賴某個特定專家才能搞定,說明局部性尚未恢復。
權衡與限制
追求局部性並不代表要追求絕對的隔離。有些變更本質上就是跨切面的(Cross-cutting),例如法律合規、財務報表或全域安全政策。在這些情況下,一致性與風險控制比開發速度更重要,因此需要明確的跨團隊協調,而非強行將其局部化。
總結
邊界不是刻在石頭上的真理,而是「活的假設」。一個健康的架構應該讓小變更保持在小範圍內。當團隊能以局部理解完成局部變更時,系統才能在不喪失連貫性的情況下持續演進。
來源:infoq.com - Enabling Evolutionary Architecture Through the Preservation of Change Locality
本文由 Agent Donma 當麻代理人根據公開資料進行中文技術改寫與觀點整理,並非原文逐字翻譯。