No-Versioning(不做版本)
No-versioning 的核心責任是把介面演進的協調成本從「版本切換」轉成「服務端的持續自我約束」。它換的是付款地點而非付款金額:沒有版本識別碼時,服務端每次變更都要保證既有消費者不會斷,而這份保證由紀律提供、不由機制提供。跟 Deprecation Lifecycle 的關係是互補的——no-versioning 讓「版本退場」這個動作消失,卻讓「單一欄位或控制項退場」變成日常,而後者仍然需要完整的退場生命週期。
概念位置
這張卡描述的是一個帶前提的立場,而非一個可以直接採用的做法。它跟 API Contract 的關係是:契約仍然存在、只是不再用版本號分期,因此每一次變更都直接作用在現行契約上。前提有兩種強度,對應兩條實務路線。
強前提是 hypermedia:client 當下能做哪些操作,由伺服器在回應裡附的連結告訴它,而不是寫死在 client 的程式碼裡。成立時服務端改變可用操作,client 讀到新的控制項集合就跟著變,版本號確實多餘。這是 Roy Fielding 對 /v1/ 式版本化建議「DON’T」的完整形式,而它在多數 JSON-over-HTTP API 並不成立——硬編碼路徑與欄位名的 client 拿不到「執行期習得」這個能力。
弱前提是欄位級宣告:client 顯式宣告自己要哪些欄位,服務端據此判斷新增是否安全。GraphQL 的 versionless 路線走的是這條,代價是三個紀律——只加不改、舊欄位以 deprecation 標注而非移除、欄位保持 nullable 預設。紀律的執行落在組織而非機制上,所以它解得了 schema 相容,解不了「還在用三年前那批欄位的團隊什麼時候能停止支援」這個組織問題。
兩個前提都不成立時,拿掉版本識別碼剩下的是「不提供版本識別、也不承諾相容」——那是把賭注押在沒有 client 依賴到被動的部分,而賭輸的證據要等消費者回報才出現。
可觀察訊號與例子
判斷自家 client 屬於哪一種,有個直接的問法:換掉某個端點的 URL、只在既有回應裡留下指向新位置的控制項,現有 client 跟得上嗎。跟得上是強前提,跟不上但只要求特定欄位是弱前提,兩者皆非就不適用這條路線。
採用弱前提路線之後最常見的失效形態,是 deprecation 標注無限期累積——「舊欄位還有誰在用」需要欄位級的用量量測才回答得了,缺了它標注就只能堆積(失效形態的完整展開見 版本策略流派之爭,量測的建法見 11.12 API 消費者用量觀測)。
設計責任
採 no-versioning 的服務端要承擔三項具體工作:建立欄位級的用量觀測(否則退場永遠沒有依據)、把「只加不改」寫進變更審查而非靠自覺、以及為舊控制項或舊欄位訂出明文的退場窗口。缺任何一項時,這條路線的成本並沒有消失,只是變得不可見。
選型時把它跟其他版本方案並置的完整推導,見 版本策略流派之爭;hypermedia 前提本身的適用邊界見 Hypermedia 適用邊界。