【问题标题】:Java Deprecated APIs and SuppressWarnings "deprecation" - practical approachJava Deprecated APIs 和 SuppressWarnings “deprecation” - 实用方法
【发布时间】:2018-10-22 11:52:12
【问题描述】:

我看到了很多using the Deprecated annotation on APIs 的示例,以便将它们标记为“需要尽快更换”。

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

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

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

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

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

参考文献:

【问题讨论】:

  • 实际上在函数被弃用一段合理的时间后删除它们。在代码库中保留已弃用的函数本身就是一种反模式。
  • @ElliottFrisch :很好的推荐,但我不想遵循已弃用方法的代码中的生命周期。关于如何自动检测弃用“超时”的任何想法?
  • @RannLifshitz 您可以添加关于何时弃用该方法的评论;但理想情况下,您没有必须弃用许多方法。
  • @ElliottFrisch:如何配置 SCA 服务器以将已弃用的 API/已弃用的 API 调用标记为阻止程序问题,大约在插入 CR 6 个月后?

标签: java deprecated suppress-warnings deprecation-warning


【解决方案1】:

第 1 步:宣布删除

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

  • API 很危险(例如,Thread.stop 方法)。

  • 有一个简单的重命名(例如,AWT Component.show/hide 替换为setVisible)。

  • 可以使用更新、更好的 API。

  • 将删除已弃用的 API。

更复杂的是,在 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(也可作为hosted service)这样的静态代码分析器来标记这些警告中的每一个。如果编译器的弃用使用警告被禁止,SonarQube 规则 "deprecated code should not be used" 甚至应该可以工作。

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

第 3 步:移除 API

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

【讨论】:

  • 非常好,+1。这正是forRemoval=true 的用途。请注意,除了具有不同文本的警告之外,现在默认启用此类“删除”警告(而不是必须使用 -Xlint:deprecation 启用;并且删除警告使用典型的@SuppressWarnings("deprecation")。(可以使用@SuppressWarnings("removal") 抑制它们,但任何这样做的人都应对实际删除 API 时代码被破坏负责。)
  • 感谢@StuartMarks,我编辑了答案以包含此内容。
【解决方案2】:

这个问题有实用的解决方案吗?

从谁的角度实用?

从经常忽略/禁止弃用警告的开发人员的角度来看,他们已经有了自己的“解决方案”……那就是忽略问题。但另一方面是其他人无法阻止他们这样做。但另一面是……最终……这不是别人的事。

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

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

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

是否有任何计划中的 JRE/JDK 功能可以帮助解决这种情况?

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

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

【讨论】:

    【解决方案3】:

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

    这个问题有实用的解决方案吗?

    是的:让弃用意味着弃用,并在宽限期后使弃用的 API 不可用,如果删除是处理它的正确方法。例如,如果您弃用存在安全风险的 API,那么在未来的版本中不将其移除会使弃用毫无用处,并且可能会被视为造成问题的原因。

    @Deprecated 注释只不过是文档,即使正如您所指出的,其他开发人员也可以简单地忽略它。

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

    【讨论】:

    • 问题在于 Java 10 有望运行为 Java 1.0/1.1 编写的代码。如果您删除了已弃用的库,则会在旧代码上遇到运行时错误。
    • @Powerlord Java 作为一个平台有它自己的要求,但这并不一定是每个人都默认采用的行为。除非您还为运行时提供客户端编译并依赖于运行时所提供的库,否则删除已弃用 API 的决定不应受到此类要求的限制。
    • @Powerlord 从 Java 9 开始,一些东西被标记为不推荐删除,这些东西将在未来的版本中被删除。换句话说:有些东西会在未来的 Java 版本中出现问题。
    • @MarkRotteveel 自 Java 2(又名 Java 1.2)以来被标记为已弃用的东西仍在 Java 中,为什么我会期望在 Java 9 中标记为已弃用的东西很快就会被删除?
    • @ErnestKiwele 人们抗拒改变。如果您开始删除 API,我可以向您保证,有些人会选择坚持使用旧的、可能不安全的 API 版本,这样他们就不必更新他们的代码。
    猜你喜欢
    • 1970-01-01
    • 2011-11-15
    • 1970-01-01
    • 1970-01-01
    • 2015-01-11
    • 1970-01-01
    • 1970-01-01
    • 2011-08-25
    相关资源
    最近更新 更多