技術債務是必然存在的,關鍵是如何管理。

本章聚焦「何時、何處」需要還債;具體「如何」進行重構請見 重構

什麼是技術債務?#

技術債務和金融債務一樣,不是絕對的壞事。適度的債務可以加速業務發展,但過多的債務會讓系統難以維護。

寶玉對技術債務的定義:

技術債務是為了短期目標而做出的、會在未來增加成本的技術決策。

技術債務的類型#

flowchart TD
    subgraph A [🎯 有意識的債務]
        A1[為了趕上市場窗口,先用簡單方案]
        A2[知道問題在哪,計劃以後修復]
        A3[這是「借貸」,需要還]
    end

    subgraph B [😵 無意識的債務]
        B1[不知道自己在製造債務]
        B2[缺乏經驗或知識]
        B3[這是「無知稅」,代價更高]
    end

    subgraph C [📅 過時的債務]
        C1[技術選型過時]
        C2[設計不再適合當前需求]
        C3[這是自然演進,難以避免]
    end

    style A fill:#e8f5e9
    style B fill:#ffebee
    style C fill:#fff3e0

技術債務的表現#

表現症狀
開發變慢改一個小功能需要很長時間
Bug 頻發修一個 Bug 引入新 Bug
難以理解新人需要很長時間上手
測試困難很難寫測試,或測試經常失敗
部署風險每次上線都提心吊膽

技術債務的成因#

業務壓力#

業務說「先上線再說」,這是技術債務最常見的來源。

喬新亮的觀點:

有時候快速上線是對的決策。問題不在於產生債務,而在於不記錄、不還債。

其他常見原因#

人員問題:
├── 經驗不足
├── 缺乏程式碼規範
├── 溝通不暢
└── 人員流動

流程問題:
├── 缺乏設計評審
├── 缺乏程式碼評審
├── 沒有重構時間
└── 測試不充分

技術問題:
├── 技術選型錯誤
├── 過度設計或設計不足
├── 複製粘貼
└── 文檔缺失

量化識別信號與戰術 vs 戰略#

前面的「表現」偏感受層面(變慢、易出 bug)。要讓識別更客觀、讓新人也能判斷,需要一組可量化的信號。

具體識別信號#

信號警戒線意涵
類別行數> 500 行職責過多,違反 SRP
方法參數個數> 5 個概念未抽象、呼叫端易錯
圈複雜度(Cyclomatic Complexity)> 15分支過多、難測難懂
「改一處要改多處」散彈式修改模組邊界沒切對
新人上手時間明顯偏長認知負荷高、缺文件
寫測試的難度寫不出/常壞依賴糾纏、可測性差

這些指標多數可由 Code Review 提到的工具(SonarQube、PMD、CheckStyle)自動掃出,納入 CI 門檻,讓技術債「看得見」。對照的壞味道見 程式碼壞味道

戰術型 vs 戰略型思維#

債務累積的根源往往不是時間不夠,而是「思維習慣」的選擇。

戰術型思維戰略型思維
目標讓功能「能跑」就好持續維持好設計
對複雜度不在意,先過再說視為首要成本,主動控制
短期看起來更快看起來稍慢
長期維護成本指數上升維護成本平穩、可持續

「能跑」不是品質標準。戰略型投資(多花一點時間把設計做對)在長期維護成本上的回報,遠超短期趕工省下的時間。這不是時間管理問題,而是要不要把「設計品質」當第一公民的取捨。

修復 vs 隔離重建的決策準則#

「重寫往往失敗」已是共識(見下方還債策略),但有些債務確實無法靠小改解決。判準如下:

flowchart TD
    A[一筆技術債] --> B{能用小步、有測試保護<br>逐步改善嗎?}
    B -->|能| C[修復:持續小改進 + 專項重構]
    B -->|不能| D{問題在於過時的<br>第三方依賴/技術選型?}
    D -->|是| E[隔離後新建:<br>包一層介面,逐步替換]
    D -->|否| F[多半仍應拆解成可小改的步驟]
  • 可修復:邏輯雖亂,但能在測試保護下小步重構——優先選此路,風險最低。
  • 隔離重建:當債務來自無法演進的外部依賴或徹底錯誤的選型,用介面把它隔離,再在背後逐步替換,而非全系統推倒重來。

管理技術債務#

識別和記錄#

第一步是識別和記錄技術債務

mindmap
  root((技術債務管理))
    🔍 識別方法
      程式碼審查中發現
      開發過程中標記(TODO、FIXME)
      Bug 分析中發現
      團隊討論中提出
      技術審計
    📝 記錄內容
      債務描述:問題是什麼
      影響範圍:影響哪些功能
      產生原因:為什麼會這樣
      修復成本:需要多少資源
      不修的代價:不修會怎樣
      優先級:什麼時候修

把技術債務當成 Issue 來管理。定期回顧,決定什麼時候修復。

優先級評估#

評估技術債務優先級的框架

維度高優先級低優先級
影響範圍影響多個功能只影響一處
頻繁程度經常遇到很少觸發
修復成本越拖越難修成本穩定
業務影響阻礙業務發展對業務無影響
安全風險有安全隱患無安全問題

還債策略#

寶玉介紹的還債方式:

持續小改進

  • 每個迭代安排一定比例的重構時間(如 20%)
  • 修改功能時順便改進相關程式碼
  • 不追求一次性解決,持續改進

專項重構

  • 對於大的技術債務,安排專項修復
  • 需要和業務溝通,獲得支援
  • 有明確的目標和計劃

重寫

  • 最後的選擇,風險和成本都很高
  • 確保真的無法通過重構解決
  • 需要詳細的遷移計劃

「讓我重寫一遍,這次肯定會更好」是危險的想法。重寫往往會製造新的問題,而且會丟失原有程式碼中的隱含知識。

預防技術債務#

預防勝於治療。預防技術債務的四個關鍵手段:

  • 編碼規範:詳見 程式碼規範
  • 設計評審:大的功能變更前先評審設計,邀請相關人員參與並記錄決策
  • 程式碼審查:詳見 Code Review
  • 適度重構:詳見 重構

童子軍規則——離開時比來時更乾淨。修改功能時順手改進相關程式碼,是最低成本的還債方式。

與業務溝通技術債務#

為什麼溝通很重要?#

技術債務往往對非技術人員不可見,但它會影響業務:

  • 開發速度變慢
  • Bug 變多
  • 創新能力下降
  • 安全風險增加

如何溝通?#

喬新亮的建議:

mindmap
  root((與業務溝通))
    🗣️ 用業務語言
      不說「程式碼耦合」,說「改一個功能要三天」
      不說「技術債務」,說「歷史遺留問題」
      不說「重構」,說「為新功能做準備」
      用資料說話:Bug 數量、開發時間
    💪 爭取資源
      說明不還債的後果
      提出具體的計劃
      承諾可見的收益
      分階段進行

平衡業務壓力#

業務壓力是真實存在的,技術團隊需要在品質和速度之間取得平衡。

平衡的方法

  • 接受有些債務是必要的
  • 但要記錄並計劃修復
  • 為重大技術債務設置紅線
  • 持續和業務溝通

案例:阿里的技術債務#

畢玄分享了阿里處理技術債務的經驗:

淘寶早期為了快速發展,積累了大量技術債務。後來花了很大力氣進行重構和升級。

教訓

  • 債務越積越多,最後不得不付出巨大代價
  • 有些債務在當時是必要的(業務優先)
  • 還債需要自上而下的支援
  • 一邊還債一邊還要支撐業務,很難

本章要點#

  1. 債務不是壞事:適度債務可以加速發展,關鍵是管理
  2. 識別和記錄:把債務當 Issue 管理,定期回顧
  3. 評估優先級:影響範圍、頻繁程度、修復成本
  4. 多種還債方式:持續小改進、專項重構、(最後)重寫
  5. 預防勝於治療:規範、評審、審查、持續重構
  6. 與業務溝通:用業務語言,用資料說話