RFC-0058:引入了已弃用的属性

RFC-0058:引入了已弃用的属性
状态已接受
区域
  • FIDL
说明

使用新的属性 Deprecated 来指明类型(枚举、结构、联合、使用声明)、常量、方法或整个接口的弃用情况。以尽可能好的方式将这些内容转换为目标语言。

作者
提交日期(年-月-日)2018-09-10
审核日期(年-月-日)2018-10-11

摘要

使用新的属性 [Deprecated] 来指明类型(枚举、结构、联合、使用声明)、常量、方法或整个接口的弃用情况。 以尽可能好的方式将这些内容转换为目标语言。

与其他 RFC 的关系

此 RFC 已被以下 RFC 取代:

设计初衷

我们添加了许多注释,表明不应再使用某种类型、方法或接口。 请参阅此处此处的示例。 通过标准化弃用信息的传达方式、在 JSON IR 中公开此信息,并在各种语言后端中利用此信息,我们可以将这些注释转换为目标语言中的警告,从而更轻松地指导开发者使用 API。

今天的用途调查

使用“ack --type=fidl -i 'deprecated' -A 2 -B 2”进行了调查

  • 方法
    • fuchsia.io/Ioctl
    • fuchsia.tracelink/RegisterTraceProviderDeprecated
    • fuchsia.modular/GetAuthenticationContext
    • fuchsia.modular/GetActiveLinks
    • fuchsia.modular/Duplicate
    • fuchsia.modular.module/ 请改用 StartOngoingActivity
    • fuchsia.mediaplayer/SetReaderSource
    • fuchsia.ui.viewsv1/AddChild
    • fuchsia.ui.viewsv1/RemoveChild
    • fuchsia.ui.viewsv1/CreateView
    • fuchsia.testing.runner/Fail
    • fuchsia.netstack/GetNodeName
    • fuchsia.netstack/SetRouteTable
  • 在字段上
    • fuchsia.modular/CreateStory -- module_url 实参
    • fuchsia.modular/CreateStoryWithInfo -- module_url 实参
    • fuchsia.modular.intent/ json -> entity_reference
  • 在界面上
    • fuchsia.simplecamera.SimpleCamera
    • fuchsia.sys.ServiceProvider
    • fuchsia.media.AudioOut
    • fuchsia.media.AudioIn

设计

建议并记录 [Deprecated] 属性的使用情况。您可以选择添加备注,说明弃用原因和首选替代方案,例如 [Deprecated = "explanation"]

FIDL 编译器未发生任何变化。 虽然我们可能希望在使用已弃用的类型或消息时显示弃用警告,尤其是在库边界上,但我们选择先实现最简单的版本。 这主要是因为我们既想了解这些 [Deprecated] 属性在实践中的使用情况,又想避免编译器中出现我们不确定未来是否需要的复杂性。

更改各种语言后端,如下一部分中详细所述:

  • 在 Rust 中,在适当的位置添加 #[deprecated]#[deprecated(note = "explanation")]

  • 在 Dart 中,根据需要添加 @Deprecated。 如果提供了说明,还应考虑添加自动注释。

  • 在 Go 中,根据需要添加注释 // Deprecated.// Deprecated: explanation.。 (请参阅三种推荐的表单。)

  • 在 C++ 中,根据需要添加 [[deprecated]][[deprecated("explanation")]]

最后,我们需要记录此功能。 在 API 评分标准的“优秀设计模式”下讨论此问题会比较合适。

有关在目标语言中放置弃用信息的具体说明

在 FIDL 中 以目标语言显示
类型别名(例如,使用 foo = bar) 没有影响,目前类型别名仅是前端问题,不会在 JSON IR 中表示。
const 声明 在所定义的常量上,以便在常量被使用时发出警告。
消息(例如结构体、并集、表格) 表示 FIDL 消息的顶级类型(类/结构体)上的注释,即最终开发者使用的类型。
字段(例如结构体字段、表字段) 在表示特定 FIDL 字段的类型的字段上,和/或在此字段的所有访问器方法(例如 ClearXxx、SetXxx 等)上
方法、事件或接口 放置在面向客户的对象/函数(例如代理)上,但不放置在面向服务客户端的对象/函数(例如,不在桩上)上;请参阅下方的注释

注意

我们可以引入 [DeprecatedForClients][DeprecatedForServices] 属性来控制弃用哪一侧,但使用显示弃用主要是为了通知消费者。

将弃用视为错误

根据 build 设置和 pragma,目标语言中的弃用注释会提升为错误。

例如,在 Rust 中,#deprecated 属性会引发警告。不过,这通常会与箱级 #![deny(warnings)] 结合使用,从而将所有警告提升为错误。 这反过来会强制已弃用的函数、变量和方法的用户在使用时指定 #allow(deprecated)。此特定使用位置正确记录了有意使用已弃用代码的意图。

再举一个例子,Go 对弃用警告的支持并不直接,需要借助 staticcheck.io 等第三方工具。

因此,FIDL 库作者应注意,引入 [Deprecated] 属性是一项源代码级重大变更,在大多数情况下,需要库用户添加新的注释。

实施策略

两点观察结果:

  • 每个语言后端都可以单独实现。
  • 可以在各种 .fidl 文件中引入 [Deprecated] 属性,而无需考虑后端支持。

建议的策略是将临时注释转换为此提议的属性,从而开始在各种 .fidl 文件中使用 [Deprecated] 属性。

在单独的更改中,处理 Dart、Rust 和 C++,因为它们具有一些目标语言支持。

对于 Go,我们希望在实现此更改的同时使用文档注释。(尤其是因为弃用通知需要与文档注释正确融合,因此一般样式是先有文档注释,然后是换行符,最后是弃用通知。)

至于文档,此更改应在 .fidl 文件中使用此属性后不久,或在一种语言后端中首次实现后不久发生。

文档和示例

API 评分标准的“优秀设计模式”部分下添加“弃用”子部分。 此外,记录此属性以及其他属性

向后兼容性

无影响。

性能

无影响。

安全

无影响。

测试

测试将在每个后端代码生成级别完成。

缺点、替代方案和未知因素

此提案的实现成本已进行衡量,并且可以一次在一个语言后端中完成。 此外,此惯例的存在将明确说明如何指示弃用,并提供有关注释现有 FIDL 文件的指南。

或者,我们可以选择不实现任何内容,并且不提供任何弃用指示支持。不执行任何操作可让我们避免在目前就承诺采用某种特定的弃用指示方式,尤其是在我们看到更多使用情况之前。 (快速确认搜索会显示大约 20-25 个位置。)

我们还可以引入一个用于弃用的语言关键字,并将其作为语法的一部分。但这似乎过于严格和复杂,尤其是对于除了文档之外没有其他语义含义的功能而言。

在先技术和参考资料

能够描述弃用情况并指出替代方案是多种编程语言(如上文所述)的常见功能。

在 protobuf 中,弃用仅允许用于字段:“如果设置为 true,则表示相应字段已弃用,新代码不应再使用该字段。在大多数语言中,此属性实际上没有任何效果。 在 Java 中,这会变成 @Deprecated 注释。未来,其他特定于语言的代码生成器可能会在字段的访问器上生成弃用注释,这反过来会导致在编译尝试使用该字段的代码时发出警告。如果该字段未被任何人使用,并且您想阻止新用户使用它,请考虑将该字段声明替换为保留语句。”

Mojo 和 Thrift 似乎没有类似的功能。

Flatbuffers,仅限字段:“不再为此字段生成访问器,代码应停止使用此数据。”