| RFC-0058:引入已弃用的属性 | |
|---|---|
| 状态 | 已接受 |
| 区域 |
|
| 说明 | 使用新的属性 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/ use StartOngoingActivity instead
- 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 argument
- fuchsia.modular/CreateStoryWithInfo -- module_url argument
- fuchsia.modular.intent/ json -> entity_reference
- 在接口中
- fuchsia.simplecamera.SimpleCamera
- fuchsia.sys.ServiceProvider
- fuchsia.media.AudioOut
- fuchsia.media.AudioIn
设计
建议并记录 [Deprecated] 属性的使用。
(可选)可以添加注释,以说明弃用原因
和首选替代方案,例如
[Deprecated = "explanation"]。
FIDL 编译器没有变化。
虽然我们可能希望在弃用类型或消息的使用中显示弃用警告(尤其是在库边界之间),但我们选择从最小实现开始。
这样做的目的是既想了解这些 [Deprecated] 属性在实践中的使用情况,又想避免编译器中出现我们不确定将来是否需要的复杂性。
更改各种语言后端,如下一部分详细所述: next section:
在 Rust 中,根据需要添加
#[deprecated]或#[deprecated(note = "explanation")]。在 Dart 中,根据需要添加
@Deprecated。 如果提供了说明,还可以考虑添加自动注释。在 Go 中,根据需要添加注释
// Deprecated.或// Deprecated: explanation.。 (请参阅三个推荐的形式。)在 C++ 中,根据需要添加
[[deprecated]]或[[deprecated("explanation")]]。
最后,我们希望记录此功能。 一个不错的做法是在 API 评分标准中的“优秀设计模式”下讨论此功能。
在目标语言中放置弃用通知的具体说明
| 在 FIDL 中 | 在目标语言中 |
|---|---|
| 类型别名(例如 using foo = bar;) | 没有影响,目前类型别名仅是前端问题,不会在 JSON IR 中表示。 |
| 常量声明 | 在定义的常量上,以便在使用常量时发出警告。 |
| 消息(例如结构体、联合、表) | 在表示 FIDL 消息的顶级类型(类/结构体)上添加注解,即最终开发者使用的类型。 |
| 字段(例如结构体字段、表字段) | 在表示特定 FIDL 字段的类型的字段上,和/或在此字段的所有访问器方法上(例如 ClearXxx、SetXxx 等)。 |
| 方法、事件或接口 | 放置在面向客户端的对象/函数(例如代理)上,而不是面向服务客户端的对象/函数(例如不在桩上);请参阅下面的注释。 |
注意
我们可以引入 [DeprecatedForClients] 和 [DeprecatedForServices] 属性来控制弃用的一方,但使用显示弃用主要是为了通知消费者。
将弃用视为错误
根据 build 设置和编译指示,目标语言中的弃用注解会提升为错误。
例如,在 Rust 中,#deprecated 属性会发出警告。不过,这通常与 crate 级 #![deny(warnings)]
结合使用,后者会将所有警告提升为错误。
这反过来又会迫使已弃用函数、变量和方法的用户
在使用时指定 #allow(deprecated)。
这种特定的使用位置可以正确记录有意使用已弃用代码的意图。
再举一个例子,Go 中对弃用警告的支持并不那么直接, 需要借助第三方工具,例如 staticcheck.io。
因此,FIDL 库作者应该意识到,引入 [Deprecated] 属性是一种源代码级重大更改,在大多数情况下,需要库用户添加新的注解。
实现策略
两点观察:
- 每种语言后端都可以独立实现。
[Deprecated]属性可以在各种 .fidl 文件中独立引入,而无需后端支持。
建议的策略是在各种 .fidl 文件中开始使用 [Deprecated] 属性,方法是将临时注解转换为此建议的属性。
在单独的更改中,处理 Dart、Rust 和 C++,因为它们有一些目标语言支持。
对于 Go,我们希望结合使用 doc comments 来实现此更改。 (尤其是因为弃用通知需要与文档注释正确融合,一般样式是文档注释、换行符,然后是弃用通知。)
至于文档,此更改应在 .fidl 文件中使用此属性后不久,或在一种语言后端中首次实现后不久发生。
文档和示例
在 API 评分标准的“优秀设计模式”部分下添加“弃用”子部分。此外,记录此属性以及其他属性。
向后兼容性
没有影响。
性能
没有影响。
安全
没有影响。
测试
测试将在每个后端代码生成级别完成。
缺点、替代方案和未知因素
此提案的实现成本是可衡量的,并且可以在每种语言后端中一次完成。 此外,此惯例的存在将明确如何指明弃用,并为注解现有 FIDL 文件提供指导。
作为替代方案,我们可以选择不实现任何内容,也不提供对任何弃用指示的支持。 不采取任何措施可以让我们避免此时承诺采用一种特定的弃用指示方式,尤其是在我们看到更多使用情况之前。 (快速 ack 搜索会返回大约 20-25 个位置。)
我们还可以引入一个用于弃用的语言关键字,并将其作为语法的一部分。这似乎过于严格和复杂,尤其是对于除了文档之外没有语义含义的功能。
在先技术和参考文档
能够描述弃用并指出替代方案是多种编程语言(上面提到了一些)的常见功能。
在 protobuf 中,仅允许对字段进行弃用:“如果设置为 true,则表示该字段已弃用,不应由新代码使用。在大多数语言中,这没有实际效果。在 Java 中,这会变成 @Deprecated 注解。 将来,其他特定于语言的代码生成器可能会在字段的访问器上生成弃用注解,这反过来会导致在编译尝试使用该字段的代码时发出警告。 如果该字段无人使用,并且您希望阻止新用户使用它,请考虑将字段声明替换为保留语句。”
Mojo 和 Thrift 似乎没有任何类似的功能。
Flatbuffers,仅适用于字段:“不再为此字段生成访问器 ,代码应停止使用此数据。”