RFC-0058:引入已废弃的属性 | |
---|---|
状态 | 已接受 |
区域 |
|
说明 | 使用新的“已废弃”属性指明类型(枚举、结构体、联合体、使用声明)、常量、方法或整个接口已废弃。尽可能以最佳方式将其转换为目标语言。 |
作者 | |
提交日期(年-月-日) | 2018-09-10 |
审核日期(年-月-日) | 2018-10-11 |
摘要
使用新的属性 [Deprecated]
指明类型(枚举、结构体、联合体、using 声明)、常量、方法或整个接口已废弃。尽可能以最佳方式将其转换为目标语言。
与其他 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]
属性来控制要废弃哪一侧,但使用显示废弃功能主要是为了告知使用方。
将废弃作为错误
根据构建设置和编译指令,目标语言中的废弃注解会被提升为错误。
例如,在 Rust 中,#deprecated
属性会引发警告。不过,这通常与 crate 级 #![deny(warnings)]
搭配使用,后者会将所有警告提升为错误。这反过来会迫使用弃用的函数、变量和方法的用户在使用时指定 #allow(deprecated)
。此特定使用情形会正确记录有意使用已废弃代码的意图。
再举一个例子,Go 中对废弃警告的支持不太直接,需要使用第三方工具(例如 staticcheck.io)。
因此,FIDL 库作者应注意,引入 [Deprecated]
属性是源代码级的破坏性更改,在大多数情况下,需要库用户添加新的注解。
实施策略
两点观察结果:
- 每个语言后端都可以单独实现。
[Deprecated]
属性可在各种 .fidl 文件中引入,而无需后端支持。
建议的策略是,通过将临时注解转换为此建议的属性,开始在各种 .fidl 文件中使用 [Deprecated]
属性。
在单独的更改中,处理 Dart、Rust 和 C++,因为它们具有一些目标语言支持。
对于 Go,我们希望在使用文档注释的同时实现此更改。(尤其是由于废弃通知需要与文档注释正确融合,因此常见的样式是先写文档注释,然后换行,最后写废弃通知。)
至于文档,此更改应在 .fidl 文件中使用此属性后不久发生,或在某个语言后端首次实现后发生。
文档和示例
在 API 评分标准的“良好设计模式”部分下,添加“废弃”子部分。此外,请将此属性与其他属性一起记录。
向后兼容性
无影响。
性能
无影响。
安全
无影响。
测试
测试将在每个后端代码生成级别进行。
缺点、替代方案和未知情况
系统会衡量此方案的实现成本,并且可以一次在每个语言后端中完成。此外,此惯例的存在已经阐明了如何指明已废弃,并提供了有关为现有 FIDL 文件添加注解的指导。
或者,我们也可以选择不实现任何内容,也不支持任何废弃指示。目前,我们不采取任何措施,以免在看到更多用例之前,就确定使用一种特定方式来指明弃用。(快速确认搜索结果大约在第 20-25 位。)
我们还可以引入一个用于废弃的语言关键字,并将其作为语法规则的一部分。这似乎过于严格且复杂,尤其是对于除了文档之外没有语义意义的功能。
在先技术和参考文档
能够描述废弃情况并指明替代方案是多种编程语言(上述一些语言)的常见功能。
在 protobuf 中,仅允许对字段进行废弃:“如果设置为 true,表示该字段已废弃,新代码不应使用该字段。在大多数语言中,这没有实际影响。在 Java 中,这会变成 @Deprecated 注解。将来,其他特定于语言的代码生成器可能会针对字段的访问器生成废弃注解,这反过来会导致在编译尝试使用该字段的代码时发出警告。If the field is not used by anyone and you want to prevent new users from using it, consider replacing the field declaration with a reserved statement."
Mojo 和 Thrift 似乎没有任何此类功能。
Flatbuffers(仅适用于字段):“请勿再为此字段生成访问器,代码应停止使用此数据。”