读书笔记《gradle-effective-implementations-guide-second-edition》维护代码质量
在进行项目时,我们希望有某种工具或流程,我们可以使用它们来查看我们的代码是否遵循某些标准;要么我们的代码没有常见的编码问题,要么它计算了代码的复杂度。
我们需要这些工具来编写更好的代码。更好的代码意味着它更容易维护,这降低了维护代码的成本。在项目团队中,我们希望确保代码遵循项目团队定义的相同标准。公司可以定义一组开发人员需要遵循的标准,作为项目启动的条件。
Java 和 Groovy 项目已经有一些工具可以用来分析和检查源代码,例如 Checkstyle, JDepend, PMD, FindBugs 和 CodeNarc。 Gradle 为这些工具中的每一个都提供了插件。在本章中,我们将看看以下插件并讨论如何在我们的项目中使用它们:
格纹风格
PMD
查找错误
依赖
CodeNarc
如果我们正在处理一个 Java 项目,并且我们将 Java 插件应用到我们的项目中,我们将得到一个名为 check
的空任务。这是 build
任务的依赖任务。这意味着当我们执行 build
任务时, check
任务也会被执行。我们可以编写自己的任务来检查项目中的某些内容,并使其成为 check
任务的依赖任务。所以如果 check
任务被执行,我们自己的任务也会被执行。不仅是我们自己编写的任务,插件也可以向check
任务添加新的依赖任务。
在本章中,我们将看到大多数插件会将一个或多个任务作为依赖任务添加到 check
任务中。这意味着我们可以将插件应用到我们的项目中,当我们调用 check
或 build
任务时,额外的插件的任务是自动执行的。
此外,check
任务依赖于 test
任务。 Gradle 将始终确保 test
任务在 check
任务之前执行,因此我们知道所有源文件和编译测试源文件,并在检查代码之前运行测试。要将 Checkstyle 分析添加到我们的项目中,我们只需应用 checkstyle
插件,如下所示:
如果我们从命令行调用 tasks
任务,我们可以看到插件已经添加了新任务:
checkstyleMain
和 checkstyleTest
任务被添加为 check
的依赖项任务。这些任务对主类和测试类运行 Checkstyle 分析。
我们还不能执行这些任务,因为我们必须在我们的项目中添加一个 Checkstyle 配置文件。此文件包含我们要应用于代码的规则。该插件会在我们项目的config/checkstyle
目录中寻找checkstyle.xml
文件。这是默认位置和文件名,但我们可以更改它。
让我们创建一个包含以下内容的配置文件:
checkstyle
插件不会自动将所需的库依赖项添加到我们的项目中。我们需要在我们的项目中添加一个适当的存储库,以便 checkstyle
插件可以下载所有依赖项。
让我们创建以下示例构建文件并添加存储库定义:
现在我们可以运行 check
任务并查看输出:
checkstyleMain
任务已执行,但构建失败,因为我们的代码不符合我们的 Checkstyle 规则。在输出中,我们可以看到所有违反规则的行为。 Gradle 还将在 build/reports/checkstyle
目录中创建一个包含违规的 XML 和 HTML 文件。
如果我们不希望构建失败,我们可以使用 checkstyle
任务的 ignoreFailures
属性。检查仍在执行并生成报告文件,但构建不会失败。
我们可以在 Gradle 构建中使用 checkstyle{}
脚本块或 checkstyle
属性配置 checkstyle 插件。脚本块接受配置闭包,我们可以在其中更改属性。在下面的构建文件中,我们将 ignoreFailures
属性设置为true,这样Checkstyle发现错误后构建也不会失败:
要更改 Gradle 使用的 Checkstyle 版本,请在 checkstyle{}
配置块中设置 toolVersion
属性。我们可以分配与 Gradle 中默认可用的版本不同的版本。
在以下示例构建文件中,我们将使用 toolVersion
属性来使用 Checkstyle 版本 5.7
:
该插件还添加了一个新的依赖配置,名为 checkstyle
。我们将使用此配置来添加 Checkstyle 工具所需的依赖项。
要更改 Checkstyle 配置文件,我们可以在 checkstyle{}
配置块中将 configFile
属性设置为不同的值。默认值为 config/checkstyle/checkstyle.xml
。例如,我们可以将 sun_checks.xml
配置文件从 Checkstyle 分发版复制到 config/checkstyle
目录。我们将使用这个新文件的值设置 configFile
属性,并使用 sun_checks.xml
配置文件。
以下示例构建文件显示我们引用了另一个 Checkstyle 配置文件:
Checkstyle 配置支持属性扩展。这意味着配置文件具有使用 ${propertyName}
语法的可变属性值。我们可以使用 Checkstyle 配置闭包的 configProperties
属性设置此类属性的值。该属性接受一个映射,其中键是 Checkstyle 配置文件中的属性名称,值是属性值。如果 Checkstyle 配置文件有一个属性,命名为 tabWidth
;例如,我们可以使用以下示例构建文件设置值:
我们使用 checkstyle{}
脚本块来更改项目中所有 checkstyle
任务的属性。但是,我们也可以在构建文件中配置单独的checkstyle
任务。我们有 checkstyleMain
和 checkstyleTest
任务,我们可以像任何其他任务一样更改它们的配置。
让我们创建以下示例构建文件并更改 checkstyleTest
任务的属性,这将覆盖 checkstyle{}脚本块:
如果我们在构建中定义了自定义源集,那么 checkstyle
插件会自动将一个checkstyle<SourceSet>
任务添加到项目。如果我们的源集被命名为 api
,那么我们可以调用 checkstyleApi
任务来只检查这个源集。 checkstyleApi
任务也被添加为 check
任务的依赖任务。因此,一旦我们运行 check
任务,Gradle 也会调用 checkstyleApi
任务。
在以下示例构建文件中,我们将创建一个名为 api
的新源集:
如果我们调用 tasks
任务,我们可以在输出中看到添加了一个新创建的任务 checkstyleApi
,这是一个 check
任务的依赖任务:
生成的报告 XML 文件放置在 build/reports/checkstyle
目录中。文件的名称基于源集名称。因此 checkstyleMain
任务将生成 build/reports/checkstyle/main.xml
报告文件。我们可以在构建文件中配置它。我们可以使用 reportsDir
属性更改包含报告的目录。我们可以使用 destination
属性更改特定 checkstyle
任务的目标文件。我们还可以使用给定任务的 enabled
属性禁用报告生成。
以下示例构建文件更改了 checkstyleMain
任务的报告目录和目标文件,并禁用了 checkstyleTest
任务的报告生成:
另一个分析 Java 源代码的工具是 PMD。它会查找未使用的变量、空的 catch 块、不必要的对象创建等。我们可以配置自己的规则集,甚至定义自己的规则。要将 PMD 与 Gradle 一起使用,我们必须将 PMD 插件应用到我们的构建中。添加插件后,我们已经安装了 pmdMain
和 pmdTest
任务。这些任务将为主要和测试源集运行 PMD 规则。如果我们有自定义源集,那么插件也会添加一个 pmd<SourceSet>
任务。这些任务也是 check
任务的依赖任务。所以如果我们调用 check
任务,所有的 pmd
任务也会被执行。
这个插件只定义了一个与 PMD 一起工作的结构,但它不包含实际的 PMD 库依赖项。 Gradle 将在我们第一次调用 pmd
任务时下载 PMD 依赖项。我们必须定义一个包含 PMD 库的存储库,例如 Bintray JCenter 存储库或公司内部网存储库。
在以下构建文件中,我们应用 pmd
插件并定义自定义源集:
当我们调用 check
任务时,如果没有违反规则,我们会得到以下输出:
注意 pmdMain
、pmdTest
和 pmdUtil
任务执行。
如果其中一个文件存在违规,则默认情况下构建将失败。我们可以将pmd
任务的ignoreFailures
属性设置为true,这样构建就不会失败。以下示例构建展示了如何将 ignoreFailures
属性设置为 true:
规则违规将在 build/reports/pmd
目录中的 XML 和 HTML 文件中报告。文件的名称与源集名称相同。我们可以更改报告目录的名称和输出文件名,也可以禁用报告生成。
以下示例构建文件使用 pmd
任务更改报告的几个属性:
如果我们不在构建文件中定义任何其他内容,则仅应用 PMD 的基本规则集。要更改应用的规则集,我们可以使用 ruleSets
属性和ruleSets()
方法。使用 ruleSets()
方法,我们可以方便地添加新规则。使用 ruleSets
属性,我们必须定义我们想要用作属性分配的所有规则。
除了配置规则集,我们还可以为 pmd
任务分配规则集文件。规则集文件包含多个规则并允许自定义规则。要添加规则集文件,我们可以使用 ruleSetFiles
属性或 ruleSetFiles()
方法。我们需要引用一个文件来设置属性或将其作为方法参数传递。
以下示例构建文件显示了如何设置规则和规则集文件:
要更改我们要使用的 PMD 版本,我们必须设置 PMD 插件的 toolVersion
属性。在编写本书时,它设置为 5.2.3 版本,但如果需要,我们可以将其更改为其他版本。在以下示例构建文件中,我们将使用 toolVersion
属性将版本简单地更改为 5.2.3:
FindBugs 是另一个我们可以用来分析源代码的库。要在我们的 Gradle 构建中使用 FindBugs,我们只需应用 findbugs
插件。我们可以将一个源代码分析插件应用到我们的项目中,也可以应用多个插件。每个工具都有不同的功能。这仅取决于我们要检查的内容或公司政策规定的内容。该插件将添加 findbugsMain
和 findbugsTest
任务来分析主要和测试源集中的源代码。如果我们有自定义源集,那么 findbugs<SourceSet>
任务也会添加到插件中。这些任务都是 check
任务的依赖任务。
与其他代码质量插件一样,Gradle 不包含 FindBugs 依赖项,但它们会在我们第一次使用 findbugs
任务时下载。我们必须包含一个存储库定义,使 Gradle 能够找到 FindBugs 依赖项。要更改正在使用的 FindBugs 版本,我们可以设置添加到我们的 findbugs
插件扩展的 toolVersion
属性 findbugs
插件的项目。
在以下构建文件中,我们将应用 findbugs
插件并配置一个额外的源集,名为 webservice
:
当我们执行 tasks
任务时,我们会看到 findbugsMain
, findbugsTest
和 findbugsWebservice
任务是 check
任务的依赖项:
如果 FindBugs 在我们的源代码中发现违反规则,那么构建将失败。我们可以将 ignoreFailures
属性设置为 true,如下面的代码行所示,以确保即使发现违规也能继续构建:
该插件在 build/reports/findbugs
目录中生成带有 FindBugs 分析结果的 XML 报告。 XML 文件的名称与所分析的源集的名称相同。我们还可以配置插件,以便生成 HTML 报告。在以下构建文件中,我们将在 findbugs
插件中配置报告:
如果我们想使用 findbugs
插件,我们可以将它们定义为依赖项。 findbugs
插件添加了一个 findbugs
依赖配置。我们可以为这个配置分配插件依赖, findbugs
任务会使用这些插件来分析代码。
要获得代码库的质量指标,我们可以使用 JDepend。 JDepend 遍历我们项目中生成的类文件,并生成设计质量指标。要使用 JDepend,我们只需在项目中应用 jdepend
插件。这将添加 jdependMain
和 jdependTest
任务。对于我们项目中的每个额外源集,都会添加一个 jdepend<SourceSet>
任务。这些任务都是 check
任务的依赖任务。
我们必须配置一个存储库,以便 Gradle 可以获取 JDepend 依赖项。 Gradle 在 Gradle 发行版中不提供 JDepend 库。这意味着我们可以轻松地使用另一个版本的 JDepend,独立于我们正在使用的 Gradle 版本。我们在其他代码质量插件中也看到了这种行为。要更改版本号,我们只需设置 jdepend
插件扩展的 toolVersion
属性。
在以下示例构建文件中,我们将应用 jdepend
插件并创建一个额外的源集:
当我们调用 tasks
任务时,我们会看到创建了三个 jdepend
任务作为 检查
任务:
jdepend
任务创建关于我们代码的统计信息。结果存储在 build/reports/jdepend
目录中的 XML 文件中。我们可以配置 jdepend
插件,以便我们存储报告的目录不同于默认目录。对于每个jdepend
任务,我们还可以更改输出格式。我们可以生成一个包含代码统计信息的文本文件,而不是 XML。我们必须在 XML 和文本之间做出选择;我们不能为单个 jdepend
任务选择两个报告输出。
以下示例构建文件显示了有关如何使用有关我们的源代码的信息更改报告的几个选项:
要检查用 Groovy 语言编写的代码,我们可以使用 CodeNarc。 CodeNarc 有几个规则可以对 Groovy 代码进行静态分析。 Gradle 有一个 codenarc
插件,因此我们可以将 CodeNarc 中的规则应用到我们的 Groovy 代码库中。如果我们应用插件,我们会自动获得一个 codenarcMain
和 codenarcTest
目标。此外,对于每个自定义源集,我们都会获得一个新的 codenarc<SourceSet>
任务。所有这些任务都是 check
任务的依赖任务。
Gradle 中不包含 CodeNarc 库。我们需要在包含 CodeNarc 的构建文件中定义一个存储库。如果我们调用 codenarc
任务,则 Gradle 会设置 CodeNarc 依赖项。我们可以通过设置插件扩展的 codenarc
属性的 toolVersion
来更改我们想要使用的CodeNarc版本。
该插件定义我们在config/codenarc
目录下提供一个名为codenarc.xml
的CodeNarc配置文件。我们可以使用插件扩展的 configFile
属性更改对配置文件的引用。
让我们创建以下示例构建文件并为 Groovy 项目应用 codenarc
插件。我们将 CodeNarc 的版本更改为我们想要使用的版本。我们还将CodeNarc配置文件的位置重新定义为 config/codenarc/custom.xml
:
当我们运行检查任务并且我们的 Groovy 代码库开始违反配置的 CodeNarc 规则时,构建将失败。如果我们不希望构建因违规而失败,我们可以将 ignoreFailures
属性设置为 true。我们可以使用 codenarc.ignoreFailures
属性为所有 codenarc
任务设置此项。我们还可以为单个codenarc
任务设置此属性。
以下构建文件显示我们可以为所有 codenarc
任务设置 ignoreFailures
属性:
codenarc
任务使用找到的结果创建一个 HTML 报告,并将其放置在 build/reports/codenarc
目录中。文件的名称由为其执行任务的源集名称定义。我们还可以选择不同的输出格式。我们可以将输出设置为 XML 或文本文件格式。我们可以使用 codenarc
任务的 reports()
方法更改报告的格式。要更改输出目录,我们可以在项目中设置 codenarc.reportsDir
属性,如下: