Java 弃用的 API 和 SuppressWarnings "deprecation" - 实用方法

Java Deprecated APIs and SuppressWarnings "deprecation" - practical approach

看到很多using the Deprecated annotation on APIs的例子,为了标记为'need to be replaced soon'。

然而,在几乎所有这些情况下,代码开发人员不仅继续使用已弃用的 APIs,而且还 suppressed the deprecation warning.

似乎 API 开发人员的最佳意图最终会创建更多与已实现的业务逻辑无关的代码 - 如果 API 已被弃用但继续与相关警告一起使用被抑制似乎充其量是代码的退化,而在最坏的情况下替换已弃用的库时似乎是潜在的应用程序断点。

这个问题有实际的解决办法吗?至少,如果它确实在 CR 中停留了相对较长的时间,是否可以将这种情况标记为代码气味?

请提出您可能正在使用的实际解决方案(库、SCA、CR 插件等......)

是否有任何计划中的 JRE/JDK 功能可以帮助解决这种情况?我的研究目前没有发现任何东西。

参考文献:

已弃用的 API 就其注释 @Deprecated 而言没有用。如果 API 客户在它被标记为已弃用多年后仍然可以成功使用它,那么可以说 API 提供商没有以任何实际方式帮助他们。

Is there a practical solution to this problem?

是:让弃用意味着弃用,并在宽限期后,使弃用的 API 不可用,如果删除是正确的处理方式。例如,如果您弃用了一个存在安全风险的 API,如果不在未来的版本中删除它,弃用就会变得毫无用处,并且会被视为导致问题的原因。

@Deprecated 注释只不过是文档,即使如您所述,其他开发人员也可以忽略它。

Java 9+ 弃用可能提供更多信息,但最终决定仍取决于使用 API 的开发人员,这并不能解决问题。

第 1 步:宣布移除

有人可能会认为弃用一个 API 意味着宣布它将被删除,但这不是唯一的用例(如 Java 7 and Java 9 的相关文章中所述):

  • The API is dangerous (for example, the Thread.stop method).

  • There is a simple rename (for example, AWT Component.show/hide replaced by setVisible).

  • A newer, better API can be used instead.

  • The deprecated API is going to be removed.

更复杂的是,在 Java 9 之前,JDK 中没有弃用的 API 被删除(参见 20 Years Of Java Deprecation),因此如果开发人员不要认真对待弃用 - 无论是在 JDK 还是在其他地方。

因此,您需要清楚地传达 API 确实、真的会被删除 。执行此操作的方法取决于编译 API 的 Java 版本。

Java 8 或更低

在这些 Java 版本中,没有正式的方法来明确区分各种弃用用例。你能做的最好的事情就是添加 Javadoc 标签 @deprecated 并且不仅给出弃用的原因和列出替代方案,而且还明确宣布你打算删除 API.

Java 9 或以上

从 Java 9 开始,使用 Enhanced Deprecation,您现在可以写

@Deprecated(forRemoval=<boolean>)

明确记录您的意图。我认为与 Javadoc @deprecated(应该详细说明弃用的原因并列出替代方案)一起,这个标准化标志是一个公平的警告。

将此标志设置为 true,编译器将对每次使用已弃用的元素发出警告,如下所示:

YourClass.java:<line>: warning: [removal] <method> in <class> has been
deprecated and marked for removal

此警告默认启用(而不是必须使用 -Xlint:deprecation 启用)并且 不会 使用 @SuppressWarnings("deprecation") 抑制。相反,人们将不得不用新的 @SuppressWarnings("removal") 来抑制它,这可能会让开发人员在没有真正充分理由的情况下三思而后行。

此外,您可以使用

明确说明引入弃用的库版本
@Deprecated(since="<version>")

在 Javadoc 或源代码中看到这一点可以帮助开发人员评估更新代码的紧急程度。

步骤 2a:运行时警告

如果情况可行,添加运行时提醒:当使用已弃用的 API 时,让它在控制台或日志文件(使用您使用的任何日志记录机制)中记录警告,宣布这将不再适用于下一个主要版本。为避免垃圾邮件,您只能记录一次(例如 private static boolean warningLogged)。

步骤 2b:静态代码分析

如果抑制了编译器的弃用使用警告,像 SonarQube (also available as a hosted service) can be set up to flag each of these warnings. The SonarQube rule "deprecated code should not be used" 这样的静态代码分析器甚至应该可以工作。

SonarQube 还会跟踪引入某个问题(即违反规则)的时间(基于版本控制),您可以根据该日期以交互方式过滤其问题列表。例如,您可以列出已在您的代码库中存在超过一年的已弃用代码的所有用法,以便您可以优先处理修复它们的工作。

第 3 步:删除 API

实际上不删除 API 会给您的 API 用户一种印象,即他们不需要费心更改代码。

Is there a practical solution to this problem?

谁的角度实用?

从经常忽略/抑制弃用警告的开发人员的角度来看,他们已经有了他们的 "solution" ... 就是忽略这个问题。但不利的一面是,其他人无法阻止他们这样做。但反面的反面是......最终......这不关别人的事。

从希望弃用他们维护的 API 的开发人员的角度来看,他们已经有了解决方案。去做就对了。然后通过实际删除弃用的 API 来完成下一步。不利的一面是,它会惹恼一些人,而另一些人则会被烧毁。 (尤其是那些经常忽略/压制弃用警告的人。但请参阅上文:那是 他们 的问题。)

从关心/负责维护组织代码库的代码质量/完整性的人的角度来看,是的,存在问题。但是解决方案相对简单:

  • 禁止代码使用@suppress("deprecation")`。
  • 禁止关闭弃用警告的构建脚本。
  • 通过 SCI 服务器插件、自定义样式检查器规则或(如果你想要粗暴的话)通过 "grepping" 源代码强制执行上述内容。
  • 对惯犯的程序员采取(比喻)大棒。

Are there any planned JRE/JDK features that might help with this situation?

如前所述,Java 9+ 增强注释支持(参见 JEP 277):

  • 提供更多信息弃用标记,并且
  • 提供了一个工具 (jdeprscan) 用于扫描针对 Java SE API 的弃用违规行为。