代码评论

在Java 9代码中寻找什么

我们以前覆盖过在Java 8代码中寻找什么,现在Java的发展速度比以往任何时候都快是时候做更新并涵盖要寻找的内容Java 9代码.虽然Java 9甚至现在已被Java 10替换为9月份的Java 11,但当然,这些Java 9功能当然可以在Java 10和11中提供。如果您的应用程序使用的任何版本超过Java 8,您可能会受益来自这些提示。

我们将使用Intellij Idea中的代码使用Upsource插件对于这些示例,因此我们可以利用IDE的全部权力来查看Java 9代码。

我们不打算讲的东西

首先,让我们来谈谈Java 9的一些特性,我们不会在代码审查的环境中提到这些特性:

  1. 尽管我们将看到使用Java模块系统,我们不会讨论何时可以将模块系统引入现有应用程序。迁移到使用Java模块可能是一个重要的体系结构决策,并且可能不是在标准代码审查期间建议的事情。
  2. 求助,JShell,是一个非常棒的用于试验代码的新工具,对于了解新特性是如何工作的非常有用。然而,使用它很可能是提出解决方案的过程的一部分,它不太可能影响我们在代码审查期间查看的工件(尽管有可能使用JShell创建和运行脚本),所以我们也不介绍JShell。

Java模块

如果你正在利用新的Java模块系统(有时被称为拼图),审阅者可以寻找的东西,以简化代码或使事情更容易理解。如果您正在使用Intellij Idea,我强烈推荐获取IDE来生成模块关系图从一个module-info.java文件,以便您可以可视化模块。

考虑在module-info.java中排序条目

这可能对您和您的团队无关,但我喜欢我的代码文件以可预测的顺序。对于module-info.java文件,我喜欢在文件的顶部并在此之后将导出组分组。

01-Module-Info订购

如果您查看Java平台代码(如上面的示例),可以看到它们按照类型对声明进行了分组,并且它们的顺序是一致的。通过这种方式,很容易一眼看到您感兴趣的部分,无论是依赖项还是该模块公开(导出)的代码。

确保只在必要的地方“打开”代码

模块化的目标之一是提高代码的安全性。它通过不再允许反射在所有代码上自动工作来做到这一点。如果我们使用依赖反射的库来工作(很多库都是这样),我们可能需要在module-info.java文件中显式声明它。

尽管最简单的解决方案是简单地声明包打开(或者,更糟糕的是,放置打开关键字在前面模块在顶部,打开模块中的所有代码),如果指定允许访问包的模块,您的代码将更加安全

05-open-specific

传递依赖关系不需要在module-info.java中

生成模块依赖关系图可以帮助审稿人查看正在使用的内容。

在下面的图表中,蓝线表示传递依赖关系——也就是说,任何依赖于第一个模块的模块都会自动获得对蓝线箭头端模块的依赖关系。

在上面的图表中,我的代码(com.mchanchitis.demo.sense.Client.)有一个依赖javafx.base,用一条细黑线表示。它还取决于javafx.controls.javafx.fxml,两者都有一个要求传递javafx.base在他们的module-info.java文件中,并且在此图表上用蓝线表示。因此,如果我想,我可以删除我的明确依赖javafx.base一切都还能正常工作。

这是一个口味问题—您可能想要显式地说明您需要的所有内容,或者您可能希望module-info.java文件尽可能小。

检查类别的可见性和模块信息中的导出水平

现在我们在Java中拥有真正的模块,我们具有始终缺少的可见性级别 - 需要由其他软件包使用但不是真正“公共”的代码。现在,如果您的代码有一个module-info.java,您的公共类不一定是公开的,即,每个人都不能被大家访问。这对安全性有益,并且还可以提供稳定的API,但能够在不影响用户的情况下更改内部。

06-module-visibility

在上面的例子中,代码作者将类的可见性从包级提高到了公共级,并将其移到了内部包中。由于这是在Java 9模块中,这意味着StringMapperProcessorClass现在不仅对包中的类可见,而且对模块中的所有类都可见。如果这个实用程序要被来自同一模块中不同包的类使用,这是完全可以的。

作为审稿人,您应该检查的一件事是,作者没有公开本应属于其他模块内部的类。

07-too-public

在这个例子中,整个内部包在模块外部被公开。因为这意味着包含只供模块本身使用的代码,这就否定了模块系统的一些好处。

在这种情况下,审稿人可能会建议:

  • 将需要从模块外部访问的特定类移动到已经导出的包中。
  • 创建一个新的、更合适的包以导出其中需要在模块外部为公共的类。注意,您还可以导出到指定的模块,因此,如果功能应该只对已知模块可见,您可以指定为出口......指令(参见这个备忘单有关module-info.java中指令的有用信息)。
  • 在需要的模块中复制所需的功能。少量的重复可能是比破坏封装更好的解决方案。

在所有情况下,冒犯出口声明需要删除。

注意,在这个例子中,包被特别地称为“内部”。当然,这也可以包含子包。这个命名约定很清楚地表明,当一个包含单词“internal”的包被添加到module-info中时,封装已经被违反了。这使得审核人员的工作更容易,因为他们可以直接看到这个问题,而不需要知道哪些包应该在模块中“保密”,哪些包可以公开给其他模块。您可能希望为您自己的模块考虑类似的命名约定。

新的集合工厂方法

从Java模块开始,让我们看一些其他代码示例,这些代码可以从Java 9的新特性中受益。

Java 9添加了集合的便利工厂方法.这意味着现在更容易创建具有固定内容集的不可变集合。

Intellij Idea(因此,Upsource内的代码智能)可以指出许多可以使用这些的示例,因此代码审阅者将能够立即发现可以从新工厂方法中受益的地方。

09-use-set-of

作为审查人员,您可能希望确保任何新添加或编辑的代码都使用了新方法,但您也可能希望检查在此审查中更改的任何文件,以查看可以迁移到新样式的现有示例。

并非所有的例子都是显而易见的。很多代码使用arrays . aslist方法从一系列值创建一个列表,然后使用该列表,就好像它是不可变的一样(arrays . aslist创建一个不能被追加的列表,但是单个值可以被更改,所以它实际上不是不可变的)。当检查代码使用arrays . aslist你可能想建议使用List.of如果可能的话,不是因为它保存了6个字符,而是因为它创建了一个更安全的列表,而无需意想不到的副作用。

10列

过程的API

如果代码所做的事情看起来像是在操作操作系统,那么使用Java 9可能会更简单。现有的流程API已经有了很多改进,太多了,不能在这里列出,所以对代码审阅者的建议是:如果代码正在使用过程的API或者做像试图获取PID的事情,研究更新后的流程API看看有没有更简单的方法。

Stackwalking API

在Java 9之前,在堆栈跟踪中查找信息是非常昂贵的,因为需要构造整个堆栈,然后我们可能要做一些事情来查看那里的信息。

Java 9增加了一个StackWalkingAPI这可能会降低堆栈跟踪中查找信息的成本。

使用这个API有点复杂,请注意,如果您想要执行的操作处理stacktrace中的每个元素(就像上面的代码所做的那样),您可能不会得到任何性能改进。和往常一样,如果性能很重要,那么就应该进行测试。

接口上的私有方法

Java 8增加了通过默认和静态方法,这在Lambda表达式的上下文中特别有用,并且为现有API添加功能而不破坏向后兼容性。

但是它确实可能导致一些代码重复。

13-code-duplication

由于根据定义,接口上的所有方法都是公共的,因此创建包含公共功能的方法意味着向接口添加一个新的公共方法,这可能不是我们所希望的。

14公共接口方法

在Java中9,接口可以有私有方法,以便代码审查人员可以建议将公共代码提取到私有方法中。

15-private-interface-method

更新弃用

Java 9添加参数到@Deprecated标签所以我们可以更清楚弃用背后的意图。第一个是字符串值,,它可以包含此代码已弃用时的版本,第二个是布尔值,forRemoval默认情况下,该方法设置为FALSE,但如果将来删除或隐藏此方法,则应为true。

查看有一个代码的代码@deprecated.注释,审阅者可以建议如果合适的情况下将额外的信息添加到此。

16-deprecated-method

如果弃用的目的是移除该方法,则forRemoval标志应设置为真正的

另一方面,当检查调用已弃用方法的代码时,停止使用已弃用方法的紧迫性(或不紧迫性)就变得很明显了。如果使用已标记为要删除的已弃用方法,IntelliJ IDEA将使用红色的划线显示。默认情况下,Upsource和IntelliJ IDEA都会在使用标记为删除的方法时给出警告。审查人员应该找出使用此方法的正当理由,理想情况下,代码作者应该利用这个机会使用任何替换。

17-using-deprecated-method

结论

Java 9最著名的特性可能是为语言增加了模块化。如果应用程序采用了Java模块系统,代码审查人员在审查更改时还要考虑另一组事情,特别是当这些更改影响Module -info. Java文件时。使用模块提供了一种封装代码的额外方法,理解这一点的代码审查人员可以充分利用模块来改进其应用程序的设计和安全性。

然而,Java 9(当然,10和11)包含除模块化以外的特征。了解这些是什么以及如何以及何时使用它们可以帮助审阅者建议对现有代码的简化。以及上面提到的特征,语言还有其他添加Streams API上的新方法可选的,这些可以帮助使代码更简洁,使用更函数式的风格。

紧跟语言和技术的代码审查人员将能够在审查的环境中建议使用新特性。IntelliJ IDEA的检查还经常会建议使用一种或几种新方法,从而更容易迁移到最新版本的Java。

然而,请记住,新事物并不一定就能让它变得更好!理解新旧之间的权衡(例如,可读性和性能)将让审稿人和作者就每种情况下的最佳方法进行富有成效的讨论。

这篇文章中的所有屏幕截图都来自Intellij Idea使用Upsource插件.当然,评论者可能希望使用Upsource UI。在下一个版本中,web用户界面将支持Java 9和10 Code Intelligence。

除了让您使用IDE提供的所有常见分析和导航功能外,插件还允许开发人员使用从他们的IDE内部进行审查吗(所有JetBrains Intellij Idea Platform IDES支持),可能涉及较小的上下文切换。有关使用插件的更详细视图,请参阅这段视频。

发现更多的

Baidu