2319 處機構分支:用 Claude Code 盤點 Legacy 系統的客製化氾濫


先給你一組數字。

在一個多租戶業務管理系統裡,if ($_SESSION['mOrgID'] == "某機構") 這種硬編碼的機構分支,散落在 661 個檔案、共 2319 處,引用了 240 個不同的機構碼、39 個機構群組。

有一行 if 串了 13 個機構 OR 比對

這就是「客製化氾濫」——每個客戶要一點不一樣的東西,十年累積下來,整個 codebase 佈滿機構分支。這篇談怎麼用 Claude Code 盤點這種氾濫,以及遷移到新框架時怎麼治理。


客製化長什麼樣子

客製化不是集中在某個 plugin 目錄,而是滲透在每個檔案裡。盤點下來有四種形態:

形態一:行內機構分支(最氾濫)

// 散在 661 個檔案、2319 處
if ($_SESSION['mOrgID'] == "ORG-N1") {
    // OrganizationC 要這樣顯示
}

// 最誇張的一行(form1a.php):13 個機構 OR
if ($_SESSION['mOrgID'] == "ORG-N1" || $_SESSION['mOrgID'] == "ORG-N2"
    || $_SESSION['mOrgID'] == "ORG-N3" || ... /* 共 13 個 */) {
    // 這些機構共用某個特殊邏輯
}

這是最難維護的形態——機構碼直接寫死在 if 裡,沒有任何抽象。改一個共用邏輯,要 grep 出所有相關的 if 分支。

形態二:機構專屬檔案

form1a.php              ← 主版
form1aORG-T1HS.php        ← 某機構客製版
form1aforA.php          ← 另一個客製版
form46_1_form2_ORG-N2.php       ← 帶機構碼的客製檔
export_employee_salary_GRP-003.php  ← 帶機構群組碼的匯出
form32_ORG-N3.php

檔名直接帶機構碼/群組碼。好處是客製邏輯隔離、不污染主版;壞處是主版改了,這些客製版常常沒跟上(一致性 checker 就是為了抓這個)。

形態三:系統設定驅動

// 比較好的形態:客製化參數存資料庫,不寫死在 code
$setting = query("SELECT * FROM system_setting WHERE OrgID = ?", [$orgID]);
if ($setting['show_special_field']) { ... }

這是最乾淨的——客製化變成資料,不是程式碼。新機構要客製,改設定就好,不用動 code。

形態四:資源檔按機構命名

title_ORG-N1.png    ← 各機構的橫幅圖
title_ORG-N2.png
...(數十個)

連 banner 圖片都按機構碼命名。


用 Claude Code 盤點氾濫程度

那組驚人的數字(661 檔 / 2319 處 / 240 機構)不是用猜的,是讓 Claude Code 掃出來的。盤點的 prompt 大致是:

掃整個 codebase,找出所有 $_SESSION['mOrgID'] == "..." 的硬編碼機構分支。
統計:總共幾處、散在幾個檔案、引用了幾個不同的機構碼。
列出機構分支最多的前 10 個檔案。

Claude Code 用 grep 抓 pattern、去重統計,幾分鐘就給出全貌。這種「跨整個 codebase 的量化盤點」是 AI 的強項——人工 grep + 數,要花一整天還容易漏。

盤點的價值:

  1. 量化技術債:「2319 處」這個數字讓客製化氾濫從「感覺很亂」變成「可衡量的負債」
  2. 找出熱點:哪幾個檔案機構分支最多(form1a.php 就是重災區)→ 優先處理
  3. 遷移評估:遷到 Laravel 時,這 2319 處每一處都要決定怎麼搬

遷移時怎麼治理

把這種系統遷到 Laravel,不能把 2319 處 if 原封不動搬過去——那只是把垃圾搬到新家。治理的方向:

策略一:行內 if → 設定驅動

// Before(Legacy):機構碼寫死
if (in_array($orgID, ["ORG-N1", "ORG-N2", "ORG-N3", /* 13 個 */])) {
    showSpecialField();
}

// After(Laravel):抽成設定
// config 或 DB:feature_flags.special_field = [list of orgs]
if (OrgFeature::enabled('special_field', $orgID)) {
    showSpecialField();
}

把「哪些機構有這個特殊邏輯」從程式碼裡的 if 變成設定裡的清單。新增機構不用改 code。

策略二:機構專屬檔 → strategy pattern

主版 + N 個客製檔 → 一個 interface + 各機構的 implementation。但這要看客製差異大不大——差異小的合併成設定,差異大的(整個版面不同)才值得獨立 class。

策略三:先盤點,分類,再決定

不是每處 if 都要重構。Claude Code 盤點後,把 2319 處分類:

類型處理
顯示差異(標題、欄位顯隱)抽成系統設定
共用邏輯的機構清單(那 13 個 OR)抽成 feature flag 清單
完全不同的版面保留獨立檔/class
已廢棄機構的分支直接刪

最有價值的發現往往是「可以刪的」——240 個機構碼裡,有些機構早就不用了,那些分支是死碼。


Claude Code 的角色

任務為什麼適合 AI
盤點:掃 2319 處、統計 240 機構跨 codebase 量化,人工做不來
分類:哪些是顯示差異、哪些是版面差異讀每處 if 的 context 判斷
找死碼:哪些機構碼已不再使用比對 orginfo 表 vs code 中的機構碼
重構:if → 設定驅動規則明確的機械式改寫

但有一條 AI 做不了:判斷哪些客製化該保留。客製化反映客戶買單的價值——某個機構要這個特殊欄位,是因為他們的業務真的需要。Claude Code 能告訴你「這裡有 2319 處分支」,但「哪些該砍、哪些是業務命脈」還是要人決定。


給其他人的借鑑

如果你維護多租戶/多客戶系統,客製化遲早會氾濫。幾個建議:

  1. 定期用 AI 盤點:每季讓 Claude Code 掃一次「客製分支有多少、引用幾個客戶」,把技術債量化
  2. 新客製優先用設定驅動:能存 DB/config 的就別寫死 if,從源頭減少氾濫
  3. 找死碼:比對「還在用的客戶」vs「code 裡出現的客戶碼」,砍掉廢棄分支
  4. 遷移前先盤點分類:別把 if 原封搬到新框架,先分類「該抽設定 / 該獨立 / 該刪」
  5. 保留判斷權:AI 盤點和重構,但「哪些客製是業務命脈」由人決定

結語

客製化氾濫不是「寫爛了」——是業務成功的副作用。每一處機構分支,背後都是一個付錢的客戶要的東西。十年下來累積成 2319 處,是這個系統養活了很多客戶的證明。

但它確實是負債。治理的第一步是看清楚規模——而「掃 661 個檔案、統計 240 個機構碼」這種事,正是 Claude Code 最擅長的。先量化,再分類,再決定哪些抽設定、哪些刪、哪些保留。

遷移到新框架是難得的治理機會:與其把 2319 處 if 原封搬過去,不如趁這次把「機構碼寫死在 code」變成「客製化是可設定的資料」。下個十年的維護者會感謝你。