本節包含 Fuchsia 貢獻者變更 Fuchsia 平台 API 的相關指南。開始之前,請先熟悉下列概念:
平台 API 的生命週期
Fuchsia 平台 API 應遵循以下生命週期: 新增 → 淘汰 → 移除 → 刪除,如下圖所示:
以下各節說明 API 開發人員如何管理這個生命週期。
新增 FIDL API
請務必使用 @available
屬性,為新的 FIDL 程式庫和元素加上註解。不穩定的 API 應在 HEAD
API 級別新增。請注意,使用 SDK 的合作夥伴可以指定 HEAD
API 級別,但如果這麼做,將無法獲得 API/ABI 相容性保證。
例如:
@available(added=HEAD)
library fuchsia.examples.docs;
API 準備好穩定運作時,您應將其更新為 added
,並在 NEXT
中進行。例如:
@available(added=NEXT)
library fuchsia.examples.docs;
NEXT
與 HEAD
類似,但 NEXT
中提供的 API 元素會自動新增至下一個發布的 API 級別。因此,如果您在 F23 的 API 凍結前一週將程式庫加入 NEXT
,一週後會看到:
@available(added=23)
library fuchsia.examples.docs;
之後,凡是新增至 23 的 API 元素,都必須支援到包含這些 API 元素的所有 API 級別都淘汰為止。
如果 FIDL 程式庫有多個 .fidl
檔案,程式庫應包含個別的 overview.fidl
檔案,且 @available
屬性應寫入該檔案,並附上說明程式庫的文件註解。詳情請參閱 FIDL 樣式指南。
SDK 類別中的每個 FIDL API 都會選擇在 CI/CQ 中進行靜態相容性測試。如果 API 變更不具回溯相容性,這些測試就會失敗。新程式庫不會指定 SDK 類別,因此不會向合作夥伴公開,也不會納入相容性測試,API 則可自由變更。API 穩定且程式庫完成 API 校正後,請指定 "partner"
類別。詳情請參閱「宣傳 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 的開發人員來說,Fuchsia 平台必須提供平穩的轉移體驗。其中一項措施是充分警告開發人員,日後將移除 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
引數。舉例來說,如要移除 18 級的方法,該方法在 12 級時已遭淘汰:
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 的特別核准,才能提交變更。
如要移除在不穩定層級 (例如 NEXT
或 HEAD
) 新增的 API,只要從 FIDL 檔案中刪除即可。
設計可順利演進的 API
本評量表著重於提升與各種平台版本的相容性。這些屬性可盡量簡化相容性維護作業,且是 FIDL API 評量標準的子集。
遵循 FIDL 樣式指南
FIDL 樣式規範可讓 FIDL 易於閱讀,並體現最佳做法。這些是通用的最佳做法,無論 sdk_category 為何,都應遵循這些做法。
使用 FIDL 版本管理註解
FIDL 版本控制註解可讓程式庫、通訊協定和其他元素與特定 API 級別建立關聯。所有相容性推理都是以 API 版本為依據。這是表示 API 演進過程中的某個時間點的方式。
請務必只在
NEXT
或HEAD
API 級別修改 API。只有在變更準備好在下一個 Fuchsia 里程碑中發布時,才應在
NEXT
中實作變更。請勿變更編號 API 級別。請參閱 version_history.json。
指定向量和字串的界限
詳情請參閱: FIDL API Rubric - Specify bounds for vector and string
使用列舉與布林值
由於布林值是二進位,因此在製作 API 時,建議使用可有多個狀態的列舉,以確保相容性。這樣一來,如果需要其他狀態,列舉可以擴充,但布林值就必須替換為其他型別。詳情請參閱: FIDL API Rubric - Avoid booleans if more states are possible。
使用彈性列舉和位元
彈性列舉具有預設的未知成員,因此可輕鬆演進列舉。
只有在極度確定這些型別絕不會擴充時,才使用 strict
、enum
和 bits
型別。strict
、enum
和 bits
類型無法擴充,如要將這些類型遷移至 flexible
,必須針對具有指定類型的每個欄位進行遷移。
詳情請參閱「FIDL 語言 - 嚴格與彈性」。
偏好使用資料表而非結構體
結構體和表格都代表具有多個具名欄位的物件。不同之處在於,結構體在傳輸格式中具有固定版面配置,這表示「無法」修改結構體,否則會破壞二進位檔的相容性。相較之下,表格在線路格式中具有彈性版面配置,這表示欄位可以隨時間新增至表格,而不會破壞二進位檔相容性。
詳情請參閱: FIDL API Rubric - Should I use a struct or table?
使用開放式通訊協定,搭配彈性方法和事件
一般來說,所有通訊協定都應為 open
,而這些通訊協定中的所有方法和事件都應為 flexible
。
將通訊協定標示為開放,可讓您更輕鬆地處理移除方法或事件的問題,因為不同元件可能是在不同版本中建構,因此每個元件對現有的方法和事件都有不同的看法。由於一般來說,我們希望通訊協定能隨著時間演進,因此建議您選擇開放式通訊協定,除非有理由選擇較封閉的通訊協定。
其中一個可能的例外狀況是撕除通訊協定,代表交易,其中唯一的雙向方法是必須嚴格執行的提交作業,而交易中的其他作業可能會演變。如果通訊協定非常小,不太可能變更,且預期由用戶端實作,您可以將其設為 closed
,所有方法也會設為 strict
。這樣一來,用戶端就不必費心決定如何處理「不明互動」。但代價是,方法或事件永遠無法新增至這類通訊協定,也無法從中移除。如果您決定要新增方法或事件,則必須定義新的撕除通訊協定來取代。
更多資訊:
使用錯誤語法
錯誤語法用於指定方法會傳回值,或發生錯誤並傳回代表錯誤的 int 或列舉。
使用自訂錯誤列舉,而非 zx.Status
定義及控管網域時,請使用專為此用途建構的列舉錯誤型別。舉例來說,如果通訊協定是專為特定用途而建構,且傳達錯誤語意是唯一設計限制,請定義列舉。
如果遵循明確定義的規格 (例如 HTTP 錯誤代碼),且列舉是代表規格所規定原始值的便利方式,請使用網域專屬的列舉錯誤型別。
詳情請參閱: FIDL API Rubric - Prefer domain specific enum for errors。
請勿使用其他程式庫的宣告
如果公開 API 的類型和通訊協定在語意上等效,重複使用這些項目並組合通訊協定是個好主意,但也很容易出錯。