我們用 SMART——Specific(具體)、Measurable(可衡量)、Achievable(可達成)、Relevant(具關聯)、Time-bound(有時限)——把每個故事拆成五天,作為每次動手造輪子前的五個檢查問題。
本篇是故事三「你的 I²C、SPI 我看不懂,先幫我包成 AT Command」的 Time-bound 篇:何時要完成?何時必須停止研究、重構或自研?
本篇定位:處理 PoC 包裝、暫時 Adapter 最後永久留存的問題。
故事的最後一個轉折,主角是我自己。硬體 bring-up 階段,為了不必每次重新編譯燒錄,我在序列埠掛了一個陽春的除錯殼(debug shell)——那是 MCU 對外接除錯工具的線,不是應用端與韌體之間不存在的線:幾條字串命令,可以讀感測器、改取樣率、倒出暫存器內容。沒有文件、沒有版本、錯誤處理隨緣——它原本只打算活到晶片穩定,使用者只有我。
某天我發現不對勁。先是隔壁同事借去展示給主管看;再過陣子,產測那邊有人問我:「你那個介面,命令格式會不會改?我們腳本有用到。」我愣在原地。我們花了好幾輪會議,用驗收清單和使用者名單擋下正式提案的 AT Command——結果一個沒經過任何評審、連名字都沒有的山寨版,正從後門悄悄轉正。而它的作者,是一路主張別隨便發明協定的我。
暫時的東西如果沒有到期日,它就不是暫時的,只是還沒被承認是永久的。探勘性的包裝——PoC、除錯工具、臨時轉接層——都是為了回答某個問題:晶片能不能動、參考驅動堪不堪用、參數該設多少。問題答完,任務就結束了;但程式不會自己消失,而「還能用」會被自然而然當成「該留著」。
更關鍵的是轉正的機制。沒有人開會決定讓我的除錯殼變成正式介面,它是每多一個使用者就多一票,一票一票轉正的。這種轉正繞過了前面辛苦建立的關卡:沒有那張驗收清單,也沒有具名使用者與維護簽名,卻正在取得同樣的地位——別人的腳本一旦依賴它,就有了事實上的契約,而這份契約沒有文件、沒有負責人,也沒有相容性承諾。最危險的介面從來不是設計得差的那種,而是從來沒被承認是介面的那種。
Time-bound 對付的就是這種安靜的永久化。方法是在暫時介面誕生那一刻就寫下三行字:它要驗證什麼假設、期限到哪一天、到期時「轉正」與「拆除」的判準各是什麼。轉正走正門——補齊契約、測試、文件與具名維護者,通過那三題的門檻;拆除的條件是假設已驗證完畢、且沒有具名使用者。適用範圍要主動標示,例如啟動訊息印上「僅供開發除錯,格式隨時會改」,別讓沉默被誤讀成承諾。誰負責也要當場指定:沒有名字的暫時介面,等於預設由「未來的某個人」承接——通常是幾個月後忘了細節的自己。
但我的除錯殼卡在更難的地方:它已經有使用者了。產測腳本正在依賴它,若直接關進開發建置(debug build)、不編入量產韌體,下次產測就停擺。「沒有價值就刪掉」在這裡不成立,因為它已經產生價值,只是那份價值長在錯的地方。所以淘汰在這裡是一段程序,不是一個決定:先公告下架日期,讓依賴它的人看得到時間表;再給一段兩者並存的遷移期,由正式測試介面補上腳本需要的功能;等腳本切換完成、跑過一輪產測驗證,舊的才移除。這條後來寫進了拆除判準——判準不只問「還有沒有人用」,也要問「不用之後,現有使用者怎麼過去」。沒有遷移路徑的下架公告,只會逼使用者偷偷留著舊版。
最後是定期盤點:每次發布前把「暫時清單」過一遍,逼每個項目表態——轉正、續期,或死亡;續期要有新理由,不能無限展延。我們那輪盤點的結果是兩個方向各走一邊:除錯殼照上面的程序退場,回到工具的本分,留在開發建置裡繼續有用,但不再是介面;轉接層反向轉正,補上文件、測試與維護人,從暫時清單除名,成為正式資產。
把五天連起來看,故事三的手擀破輪子模式就浮出來了:因為不熟悉,就要求系統改成自己熟悉的形狀。它可以來自別人——把匯流排包成一套字串命令;也可以來自自己——我的除錯殼就是我熟悉形狀的私產。可以走正門,也可以從後門。
而那次盤點是這故事最誠實的畫面:除錯殼和轉接層被放在同一張清單上,一個拆、一個轉,用的是同一套判準。誰提的、誰寫的、順不順手,都不進判準;寫不寫得出使用者的名字、找不找得到願意承擔它下半生的人,才進。
說到底,我原本只是看不懂外文說明書,最後不是去查字典,而是要求原廠替我發明一種新語言——而且差一點自己偷偷發明了一種。
但「不熟悉」還有另一條逃生路線。這個故事裡,我們把陌生的東西拖到面前捏成熟悉的形狀;有時候人會反過來——繞過看不懂的那一層,往自以為單純的更深處鑽下去。下一個故事就從那裡開始:我只是想跟一台網路攝影機要一張照片而已。