這一行取得庫存,下一行就拿來判斷能不能接單。這個判斷成立嗎?
維護訂單系統時,可能會看到這一行:
var stock = await inventory.GetAsync(productId, warehouseId);
看起來很簡單:依商品與倉庫取得庫存。但如果接下來要用這個數字判斷能否接單,我們還需要知道:資料來自DB還是快取?是倉庫現有數量,還是扣掉預留後的可售數量?這次查詢本身會不會改變庫存?
能解釋「取得庫存」與「比較數量」,還要確認這兩步接在一起是否合理。
先確認資料從哪裡來
點進方法,可能發現它先查快取,沒有資料才讀DB。再往下看,讀的也可能是查詢用的資料副本,而非承接庫存異動的主要資料庫。
這些做法各有用途。商品列表可能容許短暫延遲,但送出訂單時,能否成功預留庫存,就要由負責庫存異動的機制判斷。畫面顯示有貨,不能直接當成這筆訂單一定拿得到貨。
讀到這裡,要確認快取何時更新、資料副本如何同步,以及呼叫端拿這份資料做什麼。不是看到快取就判定有問題,而是理解它提供的資料,能否支撐後面的決定。
即使直接讀DB,查詢後也可能有其他訂單改變庫存。因此,後面的數量比較可以作為初步檢查,卻不能取代真正的庫存預留。讀程式時,要確認流程是否把這兩件事分清楚。
再確認數字包含了什麼
假設回傳庫存是10,這個10可能是實際在庫量,也可能已經扣掉其他訂單預留的數量。兩者都是整數,後面的判斷卻不能混用。
例如,倉庫有10件,其中4件已預留給其他訂單。若這個情境沒有其他限制,可售數量就是6件。拿在庫量判斷能否再接8件,會高估能接的數量;若回傳值已是6件,又自行扣一次預留量,也會算錯。
所以要往資料查詢、計算邏輯與欄位定義追:預留量在哪裡扣除?是否排除了不可售品?數量屬於指定倉庫,還是多個倉庫加總?
這裡也要分清楚「回傳值已扣除預留量」與「呼叫方法會執行預扣」。前者是數字的計算方式,後者會改變系統狀態。如果查詢內部還呼叫了預留流程,就要確認它的使用條件,不能把它當成可隨意重複執行的純讀取。
同樣一行數量比較,用在庫量或可售量,意義就不同;查詢是否已執行預留,也會影響下一步應該做什麼。
同一份資料,也有時間與範圍
背景工作拿到的訂單,可能是剛讀出的資料,也可能是幾分鐘前排入佇列時的內容。即使欄位相同,期間若已取消訂單或調整數量,原本的判斷就不一定適用。
庫存恢復也是如此。查詢原操作結果時,要確認操作識別何時建立、是否在第一次送出前保存,以及對應哪些品項與數量。查到某次操作成功,不等於已確認目前要處理的這一筆。
讀程式時,可以順著參數往前追,再看回傳值被用在哪裡。這能幫助我們發現:問題有時不在方法算錯,而是呼叫端拿了不同時間點或不同範圍的資料,做出超過資料本身能支持的判斷。
讓AI協助追查,自己核對依據
我覺得有了閱讀程式的基本功,我們就比較能明確的請AI追查呼叫關係、資料存取與快取設定。與其只請它解釋每一行,可以直接問:「這個庫存值來自哪裡?是否扣除預留量?查詢有沒有副作用?這些條件能否支持後面的接單判斷?」尤其當今天是外部服務的介面時,就不能只靠方法名稱推論回傳數量的意思就做下去。
看懂一個變數的型別與名稱之後,還要知道它從哪裡來、代表哪個時間點,以及涵蓋什麼範圍。回到開頭,取得庫存與比較數量可能各自都沒有錯,但要判斷能否接單,仍須確認數量的定義,以及後續預留是否成功。
讀懂程式,不只是知道每一行做了什麼,還要理解前一行提供的結果,是否足以支持下一行的判斷。
規格寫「庫存大於0就能接單」
上線後,一百個請求同時看到最後一件庫存,開開心心地成立了一百張訂單。
主管問:「不是測過了?」
工程師:「測過了,只是測試時大家比較有禮貌,會排隊。」
![]()