本部分包含面向对以下项进行更改的 Fuchsia 贡献者的指南: Fuchsia 平台 API。在开始之前,您应该先熟悉 以下概念:
平台 API 的生命周期
Fuchsia 平台 API 应遵循以下生命周期: 已添加 → 已弃用 → 已移除 → 已删除,如下图所示:
下面几部分将说明作为 API 开发者如何管理此生命周期。
添加 FIDL API
务必使用
@available
属性。不稳定
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;
在此之后,添加到 API 23 的所有 API 元素在 我们已停用所有包含这些 API 元素的 API 级别。
如果 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 已弃用,应改用替代 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 在 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 级或更高级别的定位则不能。开发 Fuchsia 功能的开发者
只要平台本身,平台就会发现 Run
方法的绑定
支持 10 到 17 之间的任何级别,因为平台 build 是以
所有受支持的 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。仅在更改已做好发布准备时,才应在
NEXT
实施更改 下一个 Fuchsia 里程碑。不应更改已编号的 API 级别。请参阅 version_history.json。
为矢量和字符串指定边界
更多信息: FIDL API 评分准则 - 指定矢量和字符串的边界
使用枚举与布尔值
由于布尔值是二进制数据,因此使用可能有多种状态的枚举 使 API 兼容时优先使用。这样,如果再有一个 可以扩展枚举,而布尔值必须为 替换为其他类型。更多信息: FIDL API 评分准则 - 如果存在更多状态,则避免使用布尔值。
使用灵活的枚举和位
灵活枚举具有默认的未知成员,因此允许轻松演变 。
仅当您非常有信心时,才使用 strict
enum
和 bits
类型
它们永远不会被延长strict
enum
和 bits
类型不能
扩展,迁移到 flexible
需要针对每个字段进行迁移
具有指定类型的容器。
更多信息:FIDL 语言 - 严格还是灵活
首选表而不是结构体
结构体和表都表示具有多个命名字段的对象。通过 不同之处在于,结构体在传输格式中具有固定布局, 因此无法在不破坏二进制文件兼容性的情况下对其进行修改。相比之下 表格采用线上布局灵活布局,这意味着相关字段可以 会不断添加到表中,而不会破坏二进制文件的兼容性。
更多信息: FIDL API 评分准则 - 我应该使用结构体还是表?
使用开放式协议以及灵活的方法和事件
一般来说,所有协议都应该为 open
,并且所有
这些协议应为 flexible
。
将协议标记为开放可让您更轻松地处理移除方法或 或在不同版本中构建了不同组件时, 使每个组件对存在哪些方法和事件具有不同的视图。 我们通常希望能够灵活适应不断演变的协议, 除非有理由选择 更封闭的协议。
一个可能的例外情况是表示事务的拆解协议。
其中唯一的双向方法是提交操作,
事务上的其他操作可能会发生变化。如果协议非常小
并且预计会由客户实施,那么您可以
closed
和所有方法 strict
。这样可以避免
决定如何处理“未知互动”。不过,代价是
任何方法或事件都不能添加到此类协议或从中移除。如果您
决定要添加方法或事件后,您需要定义一个新的
使用拆解协议进行替换。
更多信息:
使用错误语法
错误语法用于指定相应方法会返回 值或者输出错误,并返回表示错误的整数或枚举值。
使用自定义错误枚举,而非 zx.Status
定义和控制网域时,请使用专门构建的枚举错误类型。对于 例如,在协议是专门构建时定义一个枚举,并传递 错误的语义设计是唯一的设计约束条件。
如果您遵循明确定义的 规范(例如 HTTP 错误代码),并且该枚举旨在满足人体工学要求 来表示规范所规定的原始值。
更多信息: FIDL API 评分准则 - 首选网域特定的枚举来显示错误。
不要使用其他库中的声明
对公共 API 来说,最好重复使用类型和组合协议(如果它们 但很容易出错。