iT邦幫忙

2021 iThome 鐵人賽

DAY 15
1
DevOps

DevOps 萌新的 TeamCity 極速上手寶典系列 第 15

第十五天:用 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 裡。

參考資料


上一篇
第十四天:在 TeamCity 上執行程式碼風格檢查
下一篇
第十六天:在 TeamCity 上執行靜態分析
系列文
DevOps 萌新的 TeamCity 極速上手寶典31

1 則留言

0
Andy 安迪
iT邦新手 5 級 ‧ 2021-09-20 16:04:30

今天這麼早就發布文章~

聖佑 iT邦新手 4 級 ‧ 2021-09-20 16:05:28 檢舉

雙鐵不是開完笑的,先解決一個才有辦法專心對付另一個 XD

沒錯沒錯,我今天的也還沒寫,連假都沒時間看 ><

我要留言

立即登入留言