Fuchsia API 的演变准则

本部分包含面向对以下项进行更改的 Fuchsia 贡献者的指南: Fuchsia 平台 API。在开始之前,您应该先熟悉 以下概念:

平台 API 的生命周期

Fuchsia 平台 API 应遵循以下生命周期: 已添加 → 已弃用 → 已移除 → 已删除,如下图所示:

此图片显示了 Fuchsia 平台上一个 API 的生命周期,
  添加 API、弃用 API、移除 API,
  最终已弃用

下面几部分将说明作为 API 开发者如何管理此生命周期。

添加 FIDL API

务必使用 @available 属性。不稳定 API 应在 HEAD API 级别添加。请注意,使用 SDK 的合作伙伴 可以HEAD API 级别为目标平台,但无法做出 API/ABI 兼容性保证 。

例如:

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

当 API 达到稳定状态后,您应在以下位置将其更新为 addedNEXT。例如:

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

NEXTHEAD 类似,不同之处在于 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 提交更改。

如需移除在不稳定级别(例如 NEXTHEAD)添加的 API,请执行以下操作: 只需从 FIDL 文件中将其删除即可。

设计可灵活演变的 API

此评分准则的重点是提升与各种平台的兼容性 版本。这些属性可让您尽可能轻松地维护兼容性 是 FIDL API 评分准则的一部分。

遵循 FIDL 风格指南

FIDL 样式准则用于确保 FIDL 可读性并 实施最佳做法。这些通常是最佳做法,应 无论 sdk_category 为何,均予以遵循。

使用 FIDL 版本控制注解

FIDL 版本控制注解允许存储库、协议 以及与特定 API 级别相关联的其他元素。所有兼容性 基于 API 版本。这就是在 API 的演变历程

  • 请仅在 NEXTHEAD API 级别修改 API。

  • 仅在更改已做好发布准备时,才应在 NEXT 实施更改 下一个 Fuchsia 里程碑。

  • 不应更改已编号的 API 级别。请参阅 version_history.json

为矢量和字符串指定边界

更多信息: FIDL API 评分准则 - 指定矢量和字符串的边界

使用枚举与布尔值

由于布尔值是二进制数据,因此使用可能有多种状态的枚举 使 API 兼容时优先使用。这样,如果再有一个 可以扩展枚举,而布尔值必须为 替换为其他类型。更多信息: FIDL API 评分准则 - 如果存在更多状态,则避免使用布尔值

使用灵活的枚举和位

灵活枚举具有默认的未知成员,因此允许轻松演变 。

仅当您非常有信心时,才使用 strict enumbits 类型 它们永远不会被延长strict enumbits 类型不能 扩展,迁移到 flexible 需要针对每个字段进行迁移 具有指定类型的容器。

更多信息:FIDL 语言 - 严格还是灵活

首选表而不是结构体

结构体和表都表示具有多个命名字段的对象。通过 不同之处在于,结构体在传输格式中具有固定布局, 因此无法在不破坏二进制文件兼容性的情况下对其进行修改。相比之下 表格采用线上布局灵活布局,这意味着相关字段可以 会不断添加到表中,而不会破坏二进制文件的兼容性。

更多信息: FIDL API 评分准则 - 我应该使用结构体还是表?

使用开放式协议以及灵活的方法和事件

一般来说,所有协议都应该为 open,并且所有 这些协议应为 flexible

将协议标记为开放可让您更轻松地处理移除方法或 或在不同版本中构建了不同组件时, 使每个组件对存在哪些方法和事件具有不同的视图。 我们通常希望能够灵活适应不断演变的协议, 除非有理由选择 更封闭的协议。

一个可能的例外情况是表示事务的拆解协议。 其中唯一的双向方法是提交操作, 事务上的其他操作可能会发生变化。如果协议非常小 并且预计会由客户实施,那么您可以 closed 和所有方法 strict。这样可以避免 决定如何处理“未知互动”。不过,代价是 任何方法或事件都不能添加到此类协议或从中移除。如果您 决定要添加方法或事件后,您需要定义一个新的 使用拆解协议进行替换。

更多信息:

使用错误语法

错误语法用于指定相应方法会返回 值或者输出错误,并返回表示错误的整数或枚举值。

使用自定义错误枚举,而非 zx.Status

定义和控制网域时,请使用专门构建的枚举错误类型。对于 例如,在协议是专门构建时定义一个枚举,并传递 错误的语义设计是唯一的设计约束条件。

如果您遵循明确定义的 规范(例如 HTTP 错误代码),并且该枚举旨在满足人体工学要求 来表示规范所规定的原始值。

更多信息: FIDL API 评分准则 - 首选网域特定的枚举来显示错误

不要使用其他库中的声明

对公共 API 来说,最好重复使用类型和组合协议(如果它们 但很容易出错。