倒數第二天,講一個貫穿這三十天的坑,用兩個發生在不同地方的例子。
我有一個自己做的活動管理小工具,資料先寫在瀏覽器本機、再同步到雲端表格。
用了一陣子,開始出現怪事:明明按了儲存、畫面也顯示成功,但重新整理之後資料回到舊的。有時候好,有時候不好。
查了很久才找到:某些狀況下本機儲存寫不進去,而程式在寫入失敗時做了「安靜地回滾」——把畫面上的狀態退回去,但沒有告訴使用者。
於是每個操作都變成一場賭博,而且賭輸的時候不會有人通知你。
後來的處置有三條:動它的資料一律回讀雲端表格驗證,不信畫面;診斷用乾淨的瀏覽器視窗,排除本機殘留狀態的干擾;清除本機資料這種操作只能由人親手點。
寫這系列的第一天,我要把稿子貼進比賽網站的編輯器。
第一次貼進去,成功。後來發現內容裡有一句話要改,於是我點進編輯區、全選、重新打一遍。
工具回報「已輸入」,長度也對得上。
我照規矩回讀了一次編輯器的內容——還是舊的。
原因是那個編輯器不是普通的輸入框(它是 SimpleMDE,底下是 CodeMirror),我的點擊沒有真正落在它上面,全選選到的是整個頁面。於是「輸入」這個動作發生了,但發生在沒有人接收的地方。沒有錯誤訊息,工具那端也誠實地回報它做了它該做的事。
後來不模擬鍵盤了,改成直接請編輯器自己動手:「把內容換成這份」,然後立刻再問它一次「你現在裝的是什麼」,兩邊對不上就停:
document.querySelector('.CodeMirror').CodeMirror.setValue(text); // 請編輯器換內容
const got = document.querySelector('.CodeMirror').CodeMirror.getValue(); // 立刻回讀
if (got !== text) throw new Error('寫入不一致'); // 對不上就停
(後來把發文做成全自動腳本時,同一頁又踩了兩個形狀一樣的坑,這裡不展開——反正每一層都說自己成功了。)
然後我按下儲存草稿,又重新載入了一次頁面,確認內容還在,才按發表。
一個是網頁應用的儲存機制,一個是自動化工具跟編輯器的介面,技術上毫無關係。但它們的失敗長得一模一樣:
「執行成功」跟「狀態改變」是兩件事,而畫面只告訴你前者。
寫入端的回報,本質上是「我做了我以為該做的動作」。它不是「結果如你所願」的證明。中間可能被沙箱擋掉、被框架覆蓋、被回滾、落在錯的地方。
用一次獨立的讀取去確認。
不可靠:寫入 ──→「成功」←── 同一條流程自己說的
可靠: 寫入 ──→ 關掉 ──→ 重新打開 ──→ 讀到了嗎?
↑
換一條路徑去看,不共用剛才的任何假設
不是同一個流程回頭看自己(那還是同一組假設),是關掉、重來、重新讀一次。重新載入頁面、重新開檔案、重新查資料庫。
這件事在這三十天裡出現太多次了:改檔回報成功但檔案沒變(Day 5)、工具正常結束但沒有輸出(Day 8)、長工單讀完檔案但沒有結論(Day 10)、報告附了網址但點不到那個數字(Day 23)。
同一個病,五種穿著。
任何寫入,都要用一次獨立的讀取來確認。
寫檔就去讀那個檔,改資料就重查一次,發布就重新載入看它在不在。
這一步很煩,會讓每件事多花十幾秒。但它是這整套系統裡投報率最高的一條,因為沒有它,前面二十八天講的記錄、索引、驗證全部建立在「我以為它做了」上面。
而 AI 團隊最大的風險從來不是它做錯事,是它沒做事,而你以為它做了。
明天最後一天,算總帳。