API 文件要讓讀者知道如何使用一項能力,以及使用後可以依賴什麼。 列出名稱與型別只是起點;輸入代表什麼、失敗後資料是否改變,也需要被記錄。
本文接續〈輸入、輸出與失敗語意〉與 〈相容性與演進〉,說明如何把契約寫清楚,以及依介面種類選擇描述工具。 不預設 API 透過 HTTP 提供,也不要求使用特定語言。
查證日期:2026-11-02。本文查閱 OpenAPI 3.2.1、JSON Schema Draft 2020-12、JDK 25 文件, 以及查證當日的 Protobuf proto3 指南與 JSON Schema 官方教學;後兩者是持續更新的文件。 本文只查閱文件,未執行程式、文件產生器或服務測試;自創例子均為教學推演。
讀者需要從文件得到什麼
閱讀一項操作時,讀者要能從「想完成的事情」找到入口,再判斷自己的用法是否成立。 有用的說明通常能回答這些問題:
| 問題 | 文件應提供的資訊 |
|---|---|
| 能做什麼? | 能力與用途,避免只重述操作名稱 |
| 開始前需要什麼? | 所需物件、狀態或權限;哪些情境不在承諾範圍內 |
| 要提供什麼? | 輸入的型別、意義、單位、有效範圍與缺值處理 |
| 結果怎麼解讀? | 成功輸出的意義,以及結果與呼叫前後狀態的關係 |
| 失敗後怎麼辦? | 可辨識的失敗方式、觸發條件,以及是否仍可能產生副作用 |
| 這份說明適用哪裡? | 對應的 API 或套件版本、支援範圍與相關遷移資訊 |
| 實際用法長什麼樣? | 能說明正常使用、邊界或易誤解規則的例子 |
這些是判斷資訊是否足夠的角度,不要求每份文件都使用同一個版型。 程序內函式可能需要說明物件是否會被修改;遠端操作則還可能需要身分、期限等資訊。 應記錄哪些內容,取決於使用者真正會依賴的行為。
從一個型別,補成可使用的說明
沿用前篇的自創「設定清單標題」例子。如果文件只留下:
title: string
讀者仍不知道能否不提供、是否接受空字串、長度怎麼計算,或空白會不會被移除。
它也沒有說明設定後回傳什麼,失敗時清單是否保持原狀。
甚至 string 本身能否排除空值,仍取決於所用語言或描述格式。
以下把同一套規則整理為一段可供閱讀的文字契約片段。 這不是正式 schema 格式,也不是涵蓋部署、並行等情境的完整產品規格:
操作:設定清單標題(title)
用途:修改目前持有的一份可修改清單的標題。
範圍:只處理記憶體內的清單;不涉及檔案、網路或其他程式同時修改。
輸入:title 必須提供,且為文字字串;不接受空值,不自動轉換型別。
長度必須為 1 到 20 個 Unicode 碼位,包含兩端,不按顯示字形數計算。
原樣保留輸入,不移除空白、不截短,也不做其他轉換。
只有空白的字串只要符合長度,也是有效輸入。
成功:將標題設為輸入文字,回傳 成功(舊標題, 新標題)。
舊標題取自呼叫前,新標題是設定後的值;兩者相同也算成功。
只設定標題,不改變項目內容與順序。
失敗:未提供、空值、非字串、長度為 0 或超過 20,回傳 失敗(標題無效)。
上述失敗不改變任何清單資料。
其中的成功與失敗是概念標記,沒有指定例外、HTTP 狀態碼或實際資料格式。 它重述前篇已定義的規則,沒有替未討論的故障情況補上保證。
讓例子解釋規則
以下每列都獨立從標題「待辦」、項目內容相同的清單開始;引號只是文字的展示界線。
| 輸入 | 預期結果 | 這個例子說明什麼 |
|---|---|---|
| 「 讀書 」 | 成功(「待辦」, 「 讀書 」) | 前後空白屬於輸入,應完整保留 |
| 「待辦」 | 成功(「待辦」, 「待辦」) | 不要求新舊值不同 |
| 連續 20 個「甲」 | 成功,標題成為這 20 個「甲」 | 上限包含 20 |
| 連續 21 個「甲」 | 失敗(標題無效),清單不變 | 超出上限要拒絕,不能截短後成功 |
例子能讓抽象規則容易辨認,但只展示了少數輸入,不能代替一般規則。 例如「讀書」成功,無法推出長度上限;一個超長輸入失敗,也無法推出所有失敗都沒有副作用。
不同描述方式,各自負責什麼
同一份契約可以同時使用文字、型別、結構化描述與例子;它們提供的資訊不同。
| 描述方式 | 適合表達 | 閱讀時要留意 |
|---|---|---|
| 自然語言 | 用途、前提、欄位意義、狀態變化與取捨 | 「適當」「過長」等模糊詞需要具體定義 |
| 型別與結構化 schema | 可用欄位、資料形狀、可表達的值域限制 | 型別成立不代表業務條件與狀態規則都成立 |
| 範例 | 一次具體使用及其結果,尤其是容易誤解的地方 | 未列出的輸入仍要回到一般規則判斷 |
| 實作 | 提供者目前實際執行的行為 | 觀察到的做法未必是公開承諾,也可能是缺陷 |
機器可讀,表示工具可以解析某些資訊,不表示實作會自動遵守全部契約。 是否產生驗證程式、哪些規則真的被檢查,都要看工具與實作如何接合。 同樣地,文件產生器只能整理已有的宣告與說明,不能替空白的描述補出輸出意義或副作用保證。
依介面種類選擇描述工具
程序內 API:宣告搭配文件註解
函式庫的呼叫入口可以直接用語言的宣告與文件註解描述。 例如 JDK 25 的 Javadoc 標準 doclet 會處理宣告附近的文件註解,產生 API 的 HTML 文件。 它讓說明靠近被描述的介面,但說明內容仍需要作者撰寫。 參考 JDK 25:Javadoc 文件註解規範。
前篇引用的 Java List.get(int index) 就將方法宣告與位置、結果、越界例外的說明放在一起。
這類文件不需要先把程序內操作改寫成 HTTP 路徑,才能記錄它的契約。
參考 Java SE 25:List.get。
HTTP API:OpenAPI 與資料 schema
OpenAPI 是與程式語言無關的 HTTP API 介面描述規範,不是所有 API 的統一格式。 它可描述路徑、操作、參數與回應;資料結構可用 Schema Object 表達,並搭配描述與範例。 因此,工具產生的文件可以同時有結構資訊與供人閱讀的語意說明。 參考 OpenAPI 3.2.1:範圍、 Operation Object與 Schema Object。
JSON Schema 則描述 JSON 實例,不限於 HTTP,也不等於完整的操作契約。
Draft 2020-12 可用 type、required、minLength 等關鍵字檢查資料限制;
但通過一份輸入 schema,不能單憑這件事就知道清單是否被修改、舊標題是否取對,或目前是否有操作權限。
這些仍須由契約說明,並由處理操作的實作履行。
參考 JSON Schema Draft 2020-12:驗證詞彙。
還要區分驗證限制與註記(annotations)。
description 提供說明;default 與 examples 也屬於註記,並不因寫進 schema 就成為驗證限制。
JSON Schema 的 default 不會在驗證時自動補入缺值;examples 不用來判定輸入有效,
其中列出的值也不會因此自動經過驗證。若工具額外提供填值或範例檢查,須另確認工具行為。
參考 Draft 2020-12:註記詞彙
與官方教學:Annotations。
RPC:介面描述語言
介面描述語言(IDL,Interface Definition Language)可以記錄服務方法與訊息型別。
例如 Protobuf proto3 可在 .proto 定義服務、方法的輸入與輸出訊息;
搭配 gRPC 的編譯器外掛,可以產生相應的 RPC 程式碼。
參考 Protobuf proto3:Defining Services。
但知道某個方法接收一種訊息、回傳另一種訊息,仍不足以得知完整行為。 若把標題例子做成遠端操作,訊息定義之外,仍要交代文字處理、失敗與狀態影響; 也必須另行處理前述教學契約沒有涵蓋的網路情境,不能把它直接當成完整 RPC 規格。
讓描述與實作保持對應
維護時,先讓讀者知道自己看的文件對應哪個 API 或套件版本。
描述格式的版本與被描述 API 的版本也要區分;例如 OpenAPI 文件的 openapi 欄位
指出使用哪版描述規範,不能把它當成服務本身的版本號。
參考 OpenAPI 3.2.1:OpenAPI Object。
實務上可為同一項規則選定主要維護位置:資料限制若已放在共用 schema,其他說明就引用它, 再補充 schema 沒有表達的意義;共通行為則集中說明,避免每個操作各抄一份後逐漸分歧。 來源可以依專案選擇宣告、描述檔或文件,不需要把所有資訊強塞進同一種格式。 重點是同一項限制有明確的維護來源,衍生文件與例子能追溯回去。
當契約改變時,一起檢查描述、例子、實作與版本說明。 如果文件寫上限 20、schema 寫上限 10,不能只因其中一份能被工具讀取就認定它正確; 需要先釐清對外承諾,再修正不一致的部分。如何以可觀察行為檢查承諾,見 API 測試。
相關文件
- 介面、契約與責任:確認哪些內容屬於使用者可依賴的承諾。
- 輸入、輸出與失敗語意:查看標題例子的原始教學契約。
- 相容性與演進:理解規則改變對既有使用者的影響。
- HTTP API 契約與 OpenAPI:具體閱讀一份 HTTP 介面的結構化描述。
- API 共通知識索引:查看閱讀順序與相關主題。