Fuchsia API 發展指南

本節包含 Fuchsia 貢獻者變更 Fuuchsia Platform API 的指南。在開始之前,您應熟悉下列概念:

平台 API 的生命週期

Fuchsia 平台 API 應遵循以下生命週期:Added → Deprecated → removedd → deleted,如下圖所示:

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

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

新增 FIDL API

請一律使用 @available 屬性為新的 FIDL API 加上註解。請在 HEAD API 級別中新增不穩定的 API。請注意,根據設計,使用 SDK 的合作夥伴無法指定 HEAD API 級別。

例如:

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

穩定版 API 應為開發中 API 級別added。也就是說,從目前的開發 API 級別開始,這個 API 可供使用,不會在沒有合適的淘汰流程的情況下變更。例如:

// At the time of writing the in development level was 10.
@available(added=10)
library fuchsia.examples.docs;

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

合作夥伴 SDK 類別中的所有 API 都會在 CI/CQ 中啟用靜態相容性測試。如果 API 變更不具回溯相容性,這些測試會失敗。如果您的 API 不穩定,請考慮將其新增至內部或實驗性 SDK 類別,以防止合作夥伴使用該類別,並選擇不進行靜態相容性測試,讓 API 自由變更。API 處於穩定狀態後,請將其新增至合作夥伴類別。

取代 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

建議您一律在移除的層級淘汰 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 級別。 不過,如果淘汰與新增同等級的 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 時保留 ABI

如要移除 API,建議使用 @available 屬性。這是我們一般建議使用的方法。舉例來說,如果 API 是在級別 10 新增,則可在 12 層級移除,如下所示:

@available(added=10, removed=12)
library fuchsia.examples.docs;

在此範例中,指定等級 10 或 11 的終端開發人員會看到 fuchsia.examples.docs 程式庫的用戶端繫結,但開發人員指定級別 12 以上的開發人員則不會。如果在平台停止支援 API 級別 12 之前就已移除這個 API 的來源,API 的靜態相容性測試就會失敗,且必須獲得 //sdk/history/OWNERS 的特殊核准才能提交變更。當 Fuchsia 平台停止支援 API 級別 12 時,即可刪除 API 的原始碼。

或者,您也可以刪除大部分用途的 API 原始碼。如果是在開發 API 級別或目前支援的 API 級別中新增 API,這會將 API 從 Fuuchsia 的記錄中移除,但系統通常不允許這種做法。在這種情況下,靜態相容性測試會失敗,而您需要獲得 //sdk/history/OWNERS 的特殊核准才能提交變更。如果是在比開發 API 級別大於開發 API 級別的任何層級 (包括特殊 HEAD API 級別) 加入 API,即適用這個方法。

移除 FIDL API 時保留 ABI

您可以從 SDK 中移除 API 的用戶端繫結,防止日後的開發人員指定該 API,同時保留平台的 API 實作 (ABI)。這項功能可讓現有應用程式在較新的平台版本上執行。如果 API 已經從 SDK 中移除,但平台仍支援其 ABI,我們會表示該平台對該 API 提供舊版支援

如要維持對 API 的舊版支援,請在移除 API 時設定 legacy=true。 例如:

protocol LegacyExample {
    @available(added=10, deprecated=11, removed=12, legacy=true)
    LegacyMethod();
};

移除 Fuchsia 平台中的所有方法時,都應繼續支援舊版支援。一旦 Fuchsia 平台停止支援所有 API 級別,再移除該方法,您就可以放心移除 legacy=true 和該方法的實作。

設計可妥善改進的 API

這個評分量表的重點在於提升與各種平台版本的相容性。這些屬性是 FIDL API 評分量表的一部分,盡可能簡化相容性。

遵循 FIDL 樣式指南

FIDL 樣式指南可用來確保 FIDL 可讀取,並實踐最佳做法。這些是最佳做法,因此無論 sdk_category 為何,都應該遵循這些最佳做法。

使用 FIDL 版本管理註解

FIDL 版本管理註解可讓程式庫、通訊協定和其他元素與特定 API 級別建立關聯。所有相容性原因皆以 API 版本為基礎。這是在 API 演進過程中表達的一個點。

  • 只在 in-developmentHEAD API 級別修改 API。

  • API 級別宣告為穩定版後即無法變更。(請參閱 version_history.json)。這樣就能變更 API,但現有的 API 級別則維持不變。

指定向量和字串的界限

瞭解詳情:FIDL API 評分量表 - 指定向量和字串的邊界

使用列舉與布林值

由於布林值是二進位檔,因此如果要讓 API 相容性,建議使用可具有多個狀態的列舉。這樣一來,如果需要其他狀態,列舉就能擴充,而布林值必須替換為另一種類型。瞭解詳情: FIDL API 評分量表 - 如果可能有多個狀態,則避免使用布林值

使用彈性的列舉和位元

彈性列舉有預設的未知成員,因此可輕鬆改進列舉。

只有在「非常」確信它們不會擴充時,才使用 strict enumbits 類型。strict enumbits 類型無法延長,而遷移到 flexible 時,必須遷移指定類型的所有欄位。

更多資訊:FIDL 語言 - 嚴格與彈性

偏好資料表而非結構

結構體和表格都代表含有多個已命名欄位的物件。差別在於結構體具有固定的傳輸格式版面配置,也就是說,在不破壞二進位檔相容性的情況下,結構無法修改。相較之下,資料表採用傳輸格式的彈性版面配置,代表您可以隨著時間將欄位新增至資料表,而不會破壞二進位檔相容性。

更多資訊:FIDL API 評分量表 - 我該使用結構還是資料表?

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

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

如果將通訊協定標示為開啟,當不同的元件可能已在不同版本上建構 (例如每個元件以不同的檢視方式,瞭解存在的方法和事件) 時,將通訊協定標示為開放可讓您更輕鬆地處理移除方法或事件。由於不斷演變的通訊協定通常比較有彈性,因此除非有理由選擇較封閉的通訊協定,否則建議您選擇開啟通訊協定。

有一個潛在的例外狀況是代表交易的「拆解通訊協定」,其中唯一的雙向方法為修訂作業,其必須嚴格,而交易中的其他作業可能會發展。如果通訊協定太小且不太可能變更,且預計會由用戶端實作,您可以將該通訊協定設為 closed,並採用所有方法 strict。如此一來,用戶端就能省去決定如何處理「不明互動」的麻煩。然而,代價是,在這類通訊協定中無法新增或移除方法或事件。如果您「確實」要新增方法或事件,則必須定義新的結束通訊協定來取代該通訊協定。

更多資訊:

使用錯誤語法

「錯誤語法」可用來指定方法將傳回值,或者傳回錯誤,並傳回代表錯誤的 int 或列舉。

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

定義及控制網域時,請使用基於特定目的建立的列舉錯誤類型。例如,在通訊協定建構時定義列舉,而傳達錯誤的語意是唯一的設計限制。

採用明確定義的規格 (例如 HTTP 錯誤代碼) 時,請使用網域專屬的列舉錯誤類型,而列舉的用意是代表規格指出的原始值。

瞭解詳情:FIDL API 評分量表 - 偏好用於錯誤的網域專屬列舉

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

如果基礎 API 在語意上相等,則適合重複使用類型和撰寫通訊協定,但很容易出錯。