搜尋文件

輸入關鍵字,搜尋標題與正文。

    API文件 01/16

    介面、契約與責任

    本文提要

    API(Application Programming Interface,應用程式介面)是程式使用另一個程式元件能力的介面。 理解一個 API,不只要知道「怎麼呼叫」,還要知道「在什麼條件下,可以期待什麼結果」。 這篇從提供者與使用者的關係出發,說明介面、實作與行為契約如何分工。 不需要先熟悉特定語言、框架或網路協定。

    文件與本文目錄
    本主題文件

    API(Application Programming Interface,應用程式介面)是程式使用另一個程式元件能力的介面。 理解一個 API,不只要知道「怎麼呼叫」,還要知道「在什麼條件下,可以期待什麼結果」。 這篇從提供者與使用者的關係出發,說明介面、實作與行為契約如何分工。 不需要先熟悉特定語言、框架或網路協定。

    查證日期:2026-11-02。官方實例採 Python 3.14 與 Java SE 25 文件;本文只查閱文件。 自創例子使用文字與偽碼,未實際執行,不代表任何既有產品或標準的規定。

    誰提供能力,誰使用能力

    提供者(provider)負責實現一項能力,並說明外部程式可以如何使用。 使用者(consumer/caller)是呼叫這項能力的程式;撰寫呼叫端的開發者需要理解使用規則。 這裡的「使用者」不一定是操作畫面的人,「提供者」也不一定是遠端伺服器。

    例如 Python/C API 讓 C 或 C++ 程式使用 Python 直譯器的能力, 可用來撰寫擴充模組,也可把 Python 嵌入其他應用程式。 這個例子沒有要求以 HTTP 傳送請求,因此 API 不能直接等同網址或 JSON。 參考 Python 3.14:C API 導論。

    提供者與使用者是相對於某個介面而言的角色。 一個元件可以對外提供資料讀取能力,同時呼叫另一個元件取得資料;它在兩個邊界扮演不同角色。

    公開介面與內部實作

    可以把兩者分成兩個問題:

    表格・3 欄 2 列
    面向回答的問題讀取清單項目的例子
    對外介面使用者能做什麼、如何提出操作、能期待什麼提供清單與位置,取得該位置的項目
    內部實作提供者如何完成這項能力使用陣列、鏈結結構,或其他儲存方式

    使用者應根據介面承諾編寫程式,而不是把某次觀察到的內部做法當成保證。 但哪些內容屬於承諾,仍要看提供者公布的文件與支援政策; 語言中的 public、能匯入的名稱或能呼叫的方法,本身不足以證明它是穩定支援的 API。

    Python 的文件便區分不同穩定程度:PyUnstable 開頭的 API 可能在次版本改變, 底線開頭的私有 API 甚至可能在修補版本無預告改變。 「找得到入口」與「可以依賴哪些保證」是兩件事。 參考 Python 3.14:C API 穩定性。

    內部做法也可能影響使用成本。Java 的 List 文件指出,不同實作的索引存取成本可能不同。 因此不能只從相同的方法名稱,推定它們具備相同的效能保證。 參考 Java SE 25:List 說明。

    契約不只有名稱與型別

    API 的契約(contract)描述使用者可以依賴的規則與提供者承諾的行為。 操作名稱、參數與結果型別能交代呼叫形式,卻不一定能完整交代結果的意義。

    例如只寫「輸入位置,輸出項目」,仍不知道位置從 0 還是 1 開始, 超出範圍時會發生什麼,以及讀取是否會改變原清單。 這些問題直接影響呼叫端能否正確使用介面。

    真實例子是 Java 的 List.get(int index):文件除了方法宣告,還說明它會回傳指定位置的項目, 並規定 index < 0 或 index >= size() 時拋出 IndexOutOfBoundsException。 這些行為不能只靠參數是整數、回傳值是元素型別得知。 參考 Java SE 25:List.get。

    用一個假想介面看雙方責任

    以下是本文自訂的教學契約,與 Java、Python 的實際規則無關。 假設有個操作叫做「讀取項目」:

    TEXT
    讀取項目(items, index) → 成功(項目) 或 失敗(位置超出範圍)
    

    這個寫法只是偽碼;成功、失敗 是結果的概念標記,不指定語言、例外機制或訊息格式。

    表格・2 欄 6 列
    契約項目本例約定
    能力讀取有順序清單中的一個項目
    輸入items 是有限的有順序清單;index 是整數
    位置規則第一個位置是 0;清單長度為 n 時,有效位置是 0 ≤ index < n
    有效位置的結果回傳 成功(items 原本在 index 的項目)
    無效位置的結果若清單與整數輸入成立,但位置無效,回傳 失敗(位置超出範圍)
    狀態影響上述成功或失敗都不改變原清單的內容與順序

    為了聚焦,本例不討論其他程式同時修改清單的情況;若提供者要支援那種使用情境,須另說明規則。 本例也沒有約定非清單、非整數等輸入的處理方式,不能自行補上保證。

    前置條件與後置條件

    前置條件(precondition)是操作開始時需要成立的條件; 後置條件(postcondition)是操作結束時必須成立的條件。 Microsoft 的 Code Contracts 文件也區分正常結束與特定例外結束時的後置條件。 此處借用概念,不要求使用其工具;該文件的工具適用範圍是 .NET Framework。 參考 Microsoft:Code Contracts。

    對本例的成功路徑,可以這樣讀:

    TEXT
    呼叫前:items 是清單,index 是整數,而且 0 ≤ index < 清單長度
    呼叫後:結果是成功,值等於呼叫前指定位置的項目,原清單不變
    

    使用者負責滿足取得成功結果所需的前提;提供者負責在這些前提成立時履行承諾。 本例還額外約定了「清單與整數成立,但位置無效」的失敗路徑: 使用者不能期待成功,提供者仍須回傳約定的失敗結果並保持清單不變。

    不符合成功前提,不等於介面一定要拋出例外,也不等於提供者可以忽略已寫明的失敗保證。 要看實際契約對該情況承諾了什麼;如果文件沒有保證,就不能推定會安全失敗或自動修正。 前面的 Java 實例明定拋出例外,本例則明定回傳失敗結果,兩者各有自己的規則。

    對照三種情況

    以下每一列都獨立從 items = [「甲」, 「乙」] 開始:

    表格・3 欄 3 列
    情況呼叫與觀察如何判讀
    正常使用位置 1,得到 成功(「乙」),清單不變符合前提,也符合結果承諾
    不符合成功前提位置 2,得到 失敗(位置超出範圍),清單不變無法取得項目,但提供者遵守了明訂的失敗規則
    提供者違約位置 1,得到 成功(「甲」)使用者符合前提,提供者卻回傳錯誤位置的項目

    若位置 1 回傳「乙」,卻同時刪除原清單中的「乙」,也違反本例的契約。 結果值正確並不足夠,還要符合「原清單不變」這項可觀察的承諾。

    閱讀一個 API 時,先確認哪些事

    可以先找出它提供的能力、可依賴的入口、成功所需條件,以及結果與狀態變化的保證。 接著查看不符合條件時的規定,區分文件明訂的行為與自己推測的行為。 如果關鍵條件沒有說清楚,問題可能在契約資訊不足,不能只靠猜測實作補齊。

    本篇先建立這個閱讀方式。資料限制與錯誤的表達方式,見輸入、輸出與失敗語意; 契約演進見相容性與演進,驗證承諾的方法見 API 測試。

    相關文件