這兩個功能分開看都很合理,疊在一起我才發現誰都沒設計過的後門

你有沒有設計過那種功能——兩個都自己 review 過、自己也覺得滿合理的,結果疊在一起才發現,根本沒人設計過這條路徑?我最近剛好看到一則新聞,讓我又想起這個老問題。

某個城市的一所學校,委員會在市長就任前大約十個月,把「參與某個特定社團」新增為「特殊(傑出)市長獎」的評選標準之一——這個決定當時跟誰會得獎完全無關,單純是委員會覺得非學業表現突出的孩子也該有被看見的管道,立意不差。市長就任之後,在一場畢業典禮上親自把這座獎頒給了自己的孩子,而孩子正是透過那條新增的社團管道拿到資格的。同一段時間,這個孩子還另外通過了一個名額只有二十五個、附帶公費補助的國際交換學生甄選——這套甄選走的是完全獨立的標準(在校成績、英文檢定分數),跟市長獎八竿子打不著。兩件事分開看,各自都有一套說得通的理由:評選標準的擴充是委員會的決定,交換生甄選是另一個單位的獨立審查,連時間點都對不上因果。問題是,當這兩條「分開看都合理」的路徑,剛好都通向同一個孩子,而頒獎的人剛好又是他爸,外界要問的就不再是「哪一步違規」,而是「這兩套系統疊在一起,到底是誰設計的」——答案通常是:沒有人設計過這個疊加,它是自己長出來的。

這種事我在系統設計裡踩過,老實說還不只一次。

我自己那次:點數系統 + 會員分級

幾年前我幫一個新創做顧問,他們有兩個功能,各自的 PM 不一樣、上線時間也差了半年。第一個是「推薦碼」機制——使用者推薦朋友註冊,拿到一筆「活動點數」,目的很單純:衝新用戶。第二個是「VIP 分級」——累積到一定的「活動點數」,自動升級成 VIP,可以少付一筆年費。這個功能的假設是:活動點數高 = 這個人真的常用產品,值得留。

兩個功能各自的 spec 我都看過,單獨看都沒問題,PM 也都各自跟業務對過數字。上線三個月後,財務那邊來問我一件事:某一批帳號的 VIP 升級速度快到不合理,可是這些帳號的「真實使用行為」(登入次數、下單次數)幾乎是零。

我第一次以為是機器人刷推薦碼——查了才發現不是,推薦碼本身有基本的防刷機制,擋得住。

我第二次以為是點數計算的 bug,重新看了一次點數服務的 code,邏輯是對的,沒有算錯。

第三次我才把兩張 spec 攤開放在一起看,才看懂:推薦碼給的「活動點數」,跟 VIP 分級判斷用的「活動點數」,是同一個欄位。設計推薦碼的人沒想過這欄位會被拿去當忠誠度指標,設計 VIP 分級的人也沒想過這個欄位裡摻了推薦獎勵。兩邊都對自己那部分負責,沒人對「這個欄位被兩種語意共用」這件事負責。

真正的問題不是任何一行 code 寫錯了,是兩個團隊對同一個欄位有不同的隱含假設,而系統沒有地方強迫這兩個假設互相對照。

這其實有個學術上的名字,叫 feature interaction problem——最早是電信系統研究拿電話功能舉例的:「來電轉接」自己沒問題、「勿擾模式」自己也沒問題,兩個一起開才會發現轉接把來電轉到一個開著勿擾的人身上,誰都沒收到。市長獎跟公費資格是同一種結構,只是換了領域。

為什麼這類漏洞特別難抓

它不會在單元測試裡現形,因為每個功能的測試都是針對它自己的情境寫的。它也不太會被 code review 抓到,因為 reviewer 通常只看這次改動涉及的檔案,不會去翻半年前上線、跟這次毫無關聯的另一個功能。它甚至不會被 PM 抓到,因為兩邊的 PM 各自對自己的 KPI 負責,沒有人的職責範圍剛好涵蓋「這兩個功能疊在一起會怎樣」。

後來我們怎麼補

我們做的事其實很直白:把「活動點數」拆成兩個獨立欄位,一個是 referral_points,一個是 loyalty_score,VIP 分級只看後者。再多做一件事——每次新增一個會寫入既有欄位、或會讀既有欄位當判斷條件的功能,強制在 PR 裡列出「這個欄位目前被哪些其他功能讀取或寫入」,不是靠 code owner 自己記得,是靠一份維護中的欄位地圖。

可遷移的教訓大概是這樣:**任何一個欄位、旗標、資格判斷條件,只要被兩個以上、由不同人負責的功能共用,就該假設它遲早會被組合出一條沒人設計過的路徑。**不是因為誰粗心,是因為系統設計本來就沒有機制讓「各自合理」自動變成「合起來也合理」。

先不說了,我得去把手上另一個專案的權限判斷欄位也攤開查一次——上次查完覺得自己是不是想太多,結果隔週真的挖到一個。

這個案例是我把顧問工作中踩過的類似坑重新整理的複合示意,文章整理於 2026 年 9 月 3 日。