第十五天:用 detekt 做静态分析

在现代开发工具的辅助下,大多数的编辑器或 IDE 都已经程序码自动完成的功能,写程序已经变得相对轻松些。不过我们还是得注意一个事实,就是程序写完跟写好还是有一段差距。程序码自动完成只是让我们能更有效率的把程序写完,至於写好,还得仰赖其他机制。

若您习惯使用的是强型别的语言(比如说在这个系列里我们用的 Kotlin),编译器本身已经能协助你找出一些错误;若您习惯使用的是 IDE(比如说在这个系列里示范的 IntelliJ IDEA),通常能提供更多 Inspection 的辅助,让您能提早发现可能有问题的程序码。

但假如您用的不是强型别的程序语言,而团队成员也不是每个人都使用 IDE 等级的工具时,该如何及早找出程序码库里可能有潜在问题的程序码?又如何确保品质能一直维持住呢?

导入 detekt 静态分析工具

在 Kotlin 生态系里,detekt 是一个知名的静态分析工具,其原理是从 Kotlin 编译器取得语法树後,依照内建的规则(Rule Set)进行分析并提供改善建议。其支援多种输出格式(XML、HTML、TXT)、提供 Gradle Plugin 及 IntelliJ IDEA Plugin 方便整合,非常符合 Kotlin 开发者的需求。接着,我们将在示范专案里导入 detekt 静态分析工具。

首先打开 build.gradle.kts,在 plugins 区段新增 detekt Plugin:

plugins {
    // ...
    id("io.gitlab.arturbosch.detekt") version "1.18.1"
}

记得 Reload Gradle,让 IntelliJ IDEA 下载 detekt Plugin 至本机。完成後就会在 Gradle Tasks 的 verification Group 底下发现新增了一系列 detekt 开头的 Task。

执行 detekt 静态分析检查

为了让我们看到 detekt 的检查效果,照惯例我们得先把程序码弄烂(咦?)。首先我们在 src/main/kotlin/io.kraftsman 底下建立一个新的资料夹叫 dtos,接着把 Product Data Class 搬进去。你会看到这时候 Product 的 package 就从原本的 io.kraftsman 变成 io.kraftsman.dtos。然後我们打开 ShoppingCart,会看到 IntelliJ IDEA 帮我们多加了一行 import io.kraftsman.dtos.Product(原本不用是因为两个 Class 在同一个 Package 里,现在多了一层所以需要 Import)。在这边我们故意把这一行变成 Wildcard Import,也就是说把 import io.kraftsman.dtos.Product 变成 import io.kraftsman.dtos.*

接着我们用 detekt 来进行静态分析,直接在 IntelliJ IDEA 右边的 Gradle 面板里 verification 底下的 detekt Task 点两下,或是在终端机里执行以下指令:

$ ./gradlew detekt

> Task :detekt FAILED
style - 5min debt
        WildcardImport - [ShoppingCart.kt] at .../ShoppingCart.kt:3:1

Overall debt: 5min


FAILURE: Build failed with an exception.

您可以看到 detekt 已经指出不允许使用 Wildcard Import 的警告,同时 detekt 也会把文字版的分析报告产生在 build/reports/detekt 里,共有 XML、HTML、TXT 三种版本。

安装 detekt IntelliJ IDEA Plugin

虽然透过 Gradle 执行 detekt 非常方便,但每次写完程序才执行总觉得还是太後知後觉了一点。有没有可能在写程序的时候就让 detekt 帮我们检查呢?答案是有的,detekt 也有出 IntelliJ IDEA Plugin,让这些规则可以直接整合到 IntelliJ IDEA 的 Exception 里。

安装方式很简单,首先打开 IntelliJ IDEA 的 Plugin 设定页。在 Marketplace 里搜寻「detekt」,点击 Install 下载安装即可。

安装好需要重开 IDE,完成後记得到偏好设定里的 detekt 设定页,确认 Enable Detekt 选项有勾起来(其他选项可以视需求自行决定是否勾选)。

再回到程序码,你会发现 import io.kraftsman.dtos.* 这一行就被标记了颜色,当滑鼠移上去时,就会显示 Detekt 的警告讯息。

使用 IntelliJ IDEA 修正潜在问题

就笔者的经验,绝大多数 detekt 点出的问题,都能用 IntelliJ IDEA 快速修复功能来修正。以这个 Wildcard Import 为例,最快的修正方式,就是先把 import io.kraftsman.dtos.* 删掉,这时 IntelliJ IDEA 就会提示找不到 Product Class。我们先按 F2 就会让游标跳到发生错误的位置,然後再按 Option+Enter 呼叫快速修复功能,IntelliJ IDEA 就会自动提示以补上 Import 来修正这个问题,这时按 Enter 套用,IntelliJ IDEA 就会补上 import io.kraftsman.dtos.Product

当然目前的练习专案相对简单,不过这样的快速修复策略可以用在很多地方,IntelliJ IDEA 非常聪明的知道在各种不同的情境下可以怎麽修正,我们只需要记得 Option+Enter 这个快速键就好。

用 detekt 一并检查排版风格问题

还记得我们前两天使用 ktlint 来检查程序码的排版风格吗?detekt 其实也提供了跟 ktlint 的整合,只需要执行 $ ./gradlew detekt 就可以同时检查排版风格以及静态分析,将需要执行的 Gradle 指令缩减一些。

整合的方式很简单,只需要在 build.gradle.ktsdependencies 区段加上相依套件即可:

dependencies {
    // ...
    detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.18.1")
}

不过这边要提醒一下,detekt 的 ktlint 整合,只能触发排版风格检查,并没有整合重新排版程序码的动作喔!换句话说,假如您需要重新排版程序码的动作,还是得安装 ktlint 取得该指令。在这边笔者会建议大家在安装 Gradle Plugin 的时候还是两个都装,在 CI 上面只需要执行 detekt 指令即可,发现有排版风格问题时,再本机由人工手动执行 ktlint 的排版指令。

小结

今天跟大家讨论了如何在专案里导入 detekt 静态分析检查工具,方便我们在团队合作时能及早发现一些潜在的错误,这个工具可以在本机 IntelliJ IDEA 上执行、也能在 TeamCity 上执行,相信可以满足各种使用情境。若您使用的语言不是 Kotlin 也没关系,同样的观念在各个程序语言都有类似的工具,只要用「static analysis <程序语言名字>」就大多能找到,再整合到 IDE 和 CI 主机即可。明天我们就来试着将 detekt 整合到 TeamCity 的 Build Step 里。

参考资料


<<:  Router

>>:  [Day6]matamask安装

[Day 22] Reactive Programming - Spring WebFlux(Hello World) Part 2

前言 在上一篇成功实作最基本的WebFlux功能,看到了一些有点熟悉又有点陌生的新朋友,在这边补充说...

[Day13] 学 Reactstrap 就离 React 更近了 ~ Navbar ‧ 初识篇

前言 今天说好要来介绍 Navbar, 就是导览列,所以也是前端经常使用到的 Component。 ...

35.Local Storage

Local Storage (更准确地说是“Web Storage”)适合存储你希望进行持久化的较小...

[DAY02] 建立 Azure Machine Learning Workspace

今天我们要开始建 Azure Machine Learning(下称AML)的 workspace ...

Day 52 (JS_API)

1. API? 应用程序介面 图形库中的一组API定义了绘制指标的方式,可於图形输出装置上显示指标。...