iT邦幫忙

2026 iThome 鐵人賽

DAY 7
0
Claude AI

Claude Code陪跑:一人開發者的訂閱制SaaS架構與十大地雷實戰記系列 第 7

# Day 7|地雷#4:同一個欄位,兩張表用不同單位記錄,混用差1000倍還不報錯

  • 分享至 

  • xImage
  •  

事故現場

有一個「當某項量測值出現異常放大時通知使用者」的警報功能,上線好幾週,一次都沒觸發過。沒有人回報 bug——因為「沒有通知」看起來就像「最近沒有異常」,完全合理。直到某天一個明顯該觸發的情境它依然沉默,我才起疑。

查下去發現:警報邏輯拿 A 表的數值跟 B 表的門檻比較,而這兩張表記錄同一個概念用的單位差了一千倍。閾值永遠不可能被跨越,警報永遠不會響。

根因解剖

兩張表的身世不同:A 表是日彙總資料,當初依照上游資料源的慣例用細粒度單位存;B 表是即時資料,依照另一個資料源的慣例用粗粒度單位(1 粗粒度 = 1000 細粒度)。兩張表各自運作時都是對的,欄位名稱還長得一模一樣。

災難發生在第一次有人(就是我)寫了跨表比較的邏輯。程式碼看起來無懈可擊:

if today_value > threshold_from_other_table * MULTIPLIER:
    notify(...)   # 看起來合理,但兩邊單位差 1000 倍,永遠不成立

型別檢查抓不到(都是數字)、測試抓不到(測試資料是自己造的,兩邊自然用了同樣單位)、code review 抓不到(欄位名一樣,誰想得到單位不一樣)。

這類雷的共同特徵

它屬於我私下分類為「語意型 bug」的家族:程式碼在語法、型別、邏輯結構上全部正確,錯的是資料的語意——單位、時區(Day 6)、幣別、基準日。這類 bug 的共同點:

  • 不報錯,不當機,安靜地給出「數量級看起來合理」的錯誤答案
  • 所有自動化工具(型別檢查、linter、測試)都失效,因為錯誤不在程式碼裡,在程式碼跟現實世界的對應關係裡
  • 潛伏期長,發現時往往已經錯了很久

防線怎麼蓋

第一道:把單位寫進看得到的地方。 欄位註解、CLAUDE.md 地雷清單裡明確記錄「A 表是細粒度單位、B 表是粗粒度單位,混用差 1000 倍且不報錯」。從此 agent 寫任何跨這兩張表的邏輯,都會主動處理換算。

第二道:換算收斂到一個函式。 跟 Day 6 的時區處理同一個思路——散落各處的 * 1000 遲早有人乘錯方向,統一入口的 to_fine_unit() / to_coarse_unit() 至少讓錯誤只可能發生在一個地方。

第三道:警報類功能要驗證「會響」。 這條事故給我的最深教訓其實是測試方法論的:驗證「不該響的時候不響」很容易,驗證「該響的時候真的會響」才是警報功能的核心測試。上線前造一筆必定觸發的資料跑一次全流程,這一步當初省掉了,代價是好幾週的靜默失效。

通則

命名相同不代表語意相同。任何跨表、跨模組、跨 API 的數值搬運,先問一句:兩邊的單位、時區、基準是同一套嗎? 這一句話的成本是五秒鐘,欠下的債是三個數量級。


上一篇
# Day 6|地雷#3:資料庫時間函式預設 UTC,在地時區永遠差一截
下一篇
# Day 8|地雷#5:同一天多筆子類別資料,排序取最新一筆時悄悄拿錯
系列文
Claude Code陪跑:一人開發者的訂閱制SaaS架構與十大地雷實戰記16
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言