我們用 SMART——Specific(具體)、Measurable(可衡量)、Achievable(可達成)、Relevant(具關聯)、Time-bound(有時限)——把每個故事拆成五天,作為每次動手造輪子前的五個檢查問題。
本篇是故事五「擔心客戶看不懂 OpenAPI 文件,我急到沒看到 Postman,先刻了一個範例 App」的 Relevant 篇:這項工作與客戶價值、專案目標及交付有什麼關係?
本篇定位:討論範例程式如何意外變成長期產品,以及它與原始 API 專案是否仍然相關。
交出去大約一個月後,第一則不像「範例回饋」的訊息來了:某個下拉選單希望改成依名稱排序,我們照做了。再來是「登入之後沒多久就跳掉,能不能不要一直重登」,然後是「新同事沒有帳號,可以幫忙開一個嗎」。到某一天,客戶內部盤點系統清單時把它一起列了進去,接著問有沒有操作紀錄。
沒有一則訊息不合理。從客戶的視角看,這就是一個有登入、有畫面、每天在用的系統;他沒有義務分辨這是範例還是產品,因為我們從來沒寫過。
我們的處境於是變成:一個 API 團隊在維護一個沒有立項、沒有預算、沒排進時程的前端系統。
範例與產品的界線不在程式碼裡,在承諾裡。同一份程式碼標成「示範用」和標成「正式系統」,是兩個東西。我們沒做這個標示,界線於是由使用行為決定——只要有人天天用它做事,它就是產品。
界線一失守,責任會一整串長出來,沒有一項在 API 專案範圍內:
還有一項更麻煩:第二套隱形契約。我們對外承諾的是 OpenAPI,客戶依賴的卻是這個 App 的行為——某個錯誤被吃掉沒顯示、某個欄位預設帶了值,在他眼中都是「系統本來就這樣」。等我們改 API,客戶就會說「你們改壞了」,即使契約沒動。
Relevant 要問的是:這工作跟專案目標還有關係嗎?我們的價值主張是一組穩定、好用、有文件的 API,維護前端系統不會讓 API 更穩定。也說句公道話:範例 App 本身沒有錯,很多成熟的 API 服務都附官方範例;在有明確邊界與支援聲明時那是很好的交付——小、單一情境、原始碼公開、寫著「請勿用於正式環境」,而且有人負責。錯的不是我們寫了範例,是寫了一個完整到像產品的東西,卻沒給它產品該有的邊界。
先做最便宜的一件事:把用途與限制寫在使用者一定看得到的地方——README 第一段、啟動畫面的提示、交付信裡的一句話。講清楚三件事:這是什麼、不建議用於正式營運、遇到問題該找誰。成本極低,卻把界線從使用行為手上收回來,改由我們宣告。
接著讓範例小到不會被誤認:功能收斂到一條路徑,原始碼直接給客戶自己跑,不由我們部署、不接正式資料。一旦由我們部署維運,它在客戶眼中就是服務,怎麼標示都沒用。
如果客戶確實需要長期使用的介面,那就另外立案;要不要立,用兩個問題判斷:誰付這筆錢、誰長期維護。答不出來,代表還沒有人真的要它。
最後做一次價值比較。同樣的人力投入維護這個 App,受益的是一個客戶的一個流程;投入改善 API 使用體驗——契約補完整、錯誤訊息寫清楚、範例整理好——受益的是每一個串接方。只要每個客戶都各自要一套介面,前者的成本便隨客戶數線性成長,後者一次投入重複使用。
我們原本只是想幫客戶跨過 API 的第一道門,最後卻可能被迫長期經營門口那間臨時搭建的服務台。臨時搭建的東西難拆,不是因為蓋得牢,是因為已經有人習慣在那裡排隊。
教訓是:交付物會自己定義角色,除非我們先替它定義。沒有標示用途的東西,用途由使用者決定;沒寫下支援範圍的東西,支援範圍就是無限。這件事在寫第一行程式碼時做,成本是零;等到有人天天在用,就是一場很長的對話。
那要怎麼替它定義?靠的不只是一句免責聲明,還要有期限與退場路徑。期限該怎麼訂,到期那天又由誰決定?