Fuchsia 平台 API 演進指南

本節提供 Fuchsia 平台 API 變更的 Fuchsia 貢獻者指南。開始之前,請先熟悉下列概念:

平台 API 的生命週期

Fuchsia 平台 API 應遵循生命週期:「已新增」→「已淘汰」→「已移除」→「已刪除」,如下圖所示:

這張圖片顯示 Fuchsia 平台上 API 的生命週期,從 API 新增的版本開始,然後淘汰、移除,最後淘汰

以下各節說明如何以 API 開發人員的身分管理這個生命週期。

新增 FIDL API

請一律使用 @available 屬性為新的 FIDL 程式庫和元素加上註解。不穩定的 API 應在 HEAD API 級別新增。請注意,使用 SDK 的合作夥伴可以指定 HEAD API 級別,但這樣做無法保證 API/ABI 相容性。

例如:

@available(added=HEAD)
library fuchsia.examples.docs;

當 API 準備就緒,可穩定運作時,您應將其更新為 NEXTadded。例如:

@available(added=NEXT)
library fuchsia.examples.docs;

NEXTHEAD 類似,但 NEXT 中可用的 API 元素會自動新增至下一個發布的 API 級別。因此,如果您在 F23 的 API 凍結前一個星期,將我們的程式庫新增至 NEXT,一個星期後,您會看到:

@available(added=23)
library fuchsia.examples.docs;

之後,包含 23 加入的所有 API 元素都必須受到支援,直到包含這些 API 元素的所有 API 級別停用為止。

如果 FIDL 程式庫有多個 .fidl 檔案,則程式庫應包含個別的 overview.fidl 檔案,並在該檔案中寫入 @available 屬性,以及說明程式庫的文件註解。詳情請參閱 FIDL 樣式指南

"partner" SDK 類別中的每個 API 都會在 CI/CQ 中進行靜態相容性測試。如果 API 以回溯不相容的方式變更,這些測試就會失敗。新程式庫不會指定 SDK 類別,因此無法向合作夥伴公開,也無法納入相容性測試,且 API 可自由變更。當 API 穩定且程式庫已完成 API 校正後,請指定 "partner" 類別。

替換 FIDL API

有時您需要用新的定義取代 API。如要在 API 級別 N 執行這項操作,請使用 @available(replaced=N) 註解舊定義,並使用 @available(added=N) 註解新定義。舉例來說,您可以透過以下方式變更 API 級別 5 的常數值:

@available(replaced=5)
const MAX_LENGTH uint32 = 16;
@available(added=5)
const MAX_LENGTH uint32 = 32;

淘汰 FIDL API

請務必讓 Fuchsia 平台能為仰賴平台 API 的開發人員提供流暢的轉換作業。其中一部分是提供充分的警告,說明日後會移除 API。停用是向開發人員傳達這項資訊的一種方式。

請務必在高於移除 API 的層級淘汰 API。當開發人員指定已淘汰的 API 時,會在建構時看到該 API 已淘汰的警告,請他們改用替代方案。您應附上附註,協助最終開發人員找到替代方案。例如:

protocol Example {
    // (Description of the method.)
    //
    // # Deprecation
    //
    // (Detailed explanation of why the method is deprecated, the timeline for
    // removing it, and what should be used instead.)
    @available(deprecated=5, removed=6, note="use Replacement")
    Deprecated();

    @available(added=5)
    Replacement();
};

API 淘汰和移除之間,至少須有一個 API 級別。例如:

// These are OK.
@available(deprecated=5, removed=6)
@available(deprecated=5, removed=100)
@available(added=5, deprecated=5)

// These will not compile.
@available(deprecated=5, removed=5)
@available(deprecated=5, removed=3)

移除 FIDL API

請注意,您必須先淘汰 API,才能將其移除。

如要移除在穩定版中新增的 API,請使用 @available 屬性的 removed 引數。舉例來說,如要移除在第 12 級已淘汰的 18 級方法,請按照下列步驟操作:

protocol Example {
    @available(added=10, deprecated=12, removed=18, note="Use Go() instead")
    Run() -> ();
};

在這個範例中,如果目標開發人員指定 10 到 17 之間 (含兩者) 的任何層級,就會看到 Run 方法的用戶端繫結,但如果目標開發人員指定 18 以上層級,就不會看到。只要平台支援 10 到 17 之間的任何級別,在 Fuchsia 平台上工作的開發人員就會看到 Run 方法的繫結,因為平台建構會指定所有支援的 API 級別。

一旦平台停止支援 10 到 17 之間的所有層級,您可以視需要從 FIDL 檔案中刪除 Run 方法。如果您在這之前就將其刪除,靜態相容性測試將會失敗,且需要獲得 //sdk/history/OWNERS 特別核准才能提交變更。

如要移除在不穩定的層級 (例如 NEXTHEAD) 新增的 API,只需從 FIDL 檔案中刪除該 API。

設計可順利演進的 API

這份評分標準著重於提升與多種平台版本的相容性。這些屬性可讓相容性盡可能容易維護,也是 FIDL API 評分標準的子集。

遵循 FIDL 樣式指南

FIDL 樣式規範可讓 FIDL 易於閱讀,並納入最佳做法。這些是一般最佳做法,無論 sdk_category 為何,都應遵循。

使用 FIDL 版本註解

FIDL 版本管理註解可讓程式庫、通訊協定和其他元素與特定 API 級別建立關聯。所有相容性推論都是根據 API 版本。這是如何表示 API 演進過程中的某個點。

  • 請只在 NEXTHEAD API 級別修改 API。

  • 只有在變更已準備好在下一個 Fuchsia 里程碑中發布時,才應在 NEXT 實作變更。

  • 請勿變更編號 API 級別。請參閱 version_history.json

指定向量和字串的邊界

詳情請參閱:FIDL API 評量標準 - 指定向量和字串的邊界

使用列舉和布林值

由於布林值是二進位值,因此在製作相容性友善的 API 時,建議使用可具有多種狀態的列舉。這樣一來,如果需要額外的狀態,則可擴充列舉,而布林值則必須替換為其他類型。詳情請參閱:FIDL API 評量標準 - 避免使用布林值,除非有更多狀態可用

使用彈性的列舉和位元

彈性列舉具有預設的不明成員,因此可輕鬆進化列舉。

只有在您非常確定不會擴充 strict enumbits 類型時,才應使用這類型別。strict enumbits 類型無法擴充,且若要將這些類型遷移至 flexible,則必須為具有指定類型的每個欄位進行遷移。

詳情請參閱:FIDL 語言 - 嚴格與彈性模式

偏好使用表格而非結構

結構體和資料表都代表具有多個已命名欄位的物件。差異在於結構體在傳輸格式中具有固定的版面配置,也就是說,如果要修改結構體,就必須破壞二進位相容性。相較之下,資料表在線格格式中具有彈性的版面配置,這表示欄位「可以」隨時間新增至資料表,而不會破壞二進位相容性。

詳情請參閱:FIDL API 評量標準 - 我該使用結構體還是資料表?

使用開放式通訊協定,搭配靈活的方法和事件

一般來說,所有通訊協定都應為 open,而這些通訊協定中的所有方法和事件都應為 flexible

將通訊協定標示為開放後,當不同元件可能在不同版本中建構時,您就能更輕鬆地處理移除的方法或事件,因為每個元件對存在哪些方法和事件的觀點不同。由於一般來說,我們都希望通訊協定具有彈性,因此建議您選擇開放式通訊協定,除非有理由選擇較封閉的通訊協定。

撕裂式通訊協定是其中一個可能的例外狀況,代表交易,其中唯一的雙向方法是必須嚴格的提交作業,而交易的其他作業可能會演變。如果通訊協定很小、不太可能變更,且預期會由用戶端實作,您可以將其設為 closed,並將所有方法設為 strict。這樣一來,用戶端就不必煩惱如何處理「不明互動」。不過,這類通訊協定無法新增或移除方法或事件。如果您決定新增方法或事件,就必須定義新的分離通訊協定來取代現有通訊協定。

更多資訊:

使用錯誤語法

錯誤語法用於指定方法會傳回值,或傳回代表錯誤的 int 或列舉。

請使用自訂錯誤列舉,而非 zx.Status

定義及控制網域時,請使用專門建構的列舉錯誤類型。舉例來說,在通訊協定專門建構時定義列舉,且傳達錯誤的語義是唯一的設計限制。

當您遵循明確定義的規格 (例如 HTTP 錯誤代碼) 時,請使用特定領域的列舉錯誤類型,而列舉是一種符合人體工學的方式,可用來表示規格規定的原始值。

詳情請參閱:FIDL API Rubric - 偏好用於錯誤的網域專用列舉

請勿使用其他程式庫的宣告

如果公用 API 的類型和組合通訊協定在語意上相同,那麼重複使用這些類型和組合通訊協定會是個好方法,但也容易出錯。