第十三天:用 ktlint 做程序码风格检查

当我们自己一个人写程序的时候,只要程序码没有写错,排版风格爱怎麽写就怎麽写,什麽时候要换行、什麽时候要空行都可自己决定。但团队合作时就不一样了,假如每个成员写程序码的排版风格都不一样的话,每个人都要花额外的精神去「适应」别人写的程序码,这样就会耗损一些团队效率。

导入 ktlint 检查排版风格

这时我们可以在专案里导入 Linter 的机制。也就是说我们可以预先定义好程序码排版的规则(Rule),然後由排版程序帮我们检查。若有风格不符合的部份会逐一列出,我们再进行修正即可。这种 Linter 工具广泛地出现在各个程序语言生态系中,甚至有些程序语言就内建 fmt 之类的工具。

在 Kotlin 生态系里,我们可以使用由 Pinterest 团队推出的 ktlint,其排版规则来自 Kotlin 官方Android 团队 ,也支援扩充 Ruleset。专案原本是以 CLI 工具的方式发布,但也有社群整合好的 Gradle Plugin 方便使用。

接下来我们就来示范如何安装 ktlint 在我们的练习专案里。

安装 ktlint Gradle Plugin

首先开启专案根目录底下的 build.gradle.kts,在 plugins 区段里新增 org.jmailen.kotlinter,更新後的 Build Script 看起来会像这样:

plugins {
    // ...
    id("org.jmailen.kotlinter") version "3.6.0"
}

别忘了 Reload Gradle 喔!Reload 後我们会在 IntelliJ IDEA 的 Gradle 面板里 Tasks 底下看到多了一个 formatting 的群组,里面有 lintKotlin 的任务可以执行。为了测试它的功效,我们先把原本写好的程序码固定弄乱,删掉一些空行、增加一些不必要的空白等,然後对 lintKotlin 点两下,Gradle 就会使用 ktlint 来检查专案程序码的排版风格。

> Task :lintKotlinMain FAILED
.../ShoppingCart.kt:1:1: Lint error > [final-newline] File must end with a newline (\n)
.../ShoppingCart.kt:10:22: Lint error > [colon-spacing] Missing spacing after ":"
.../ShoppingCart.kt:10:25: Lint error > [curly-spacing] Missing spacing around "{"
.../ShoppingCart.kt:10:26: Lint error > [indent] Missing newline after "{"

ktlint 检查完成後,应该会看到类似像上面的这种输出。ktlint 会指出在哪个档案的哪一行的哪一栏找到不合排版风格的程序码以及原因,我们就可以依照这个清单开始修正。

使用 ktlint 修正程序码排版

不过我们都是人,要手动一个一个修正也太累了吧?这个练习专案的档案还不多,修正起来或许还算容易,假如是大型专案,动辄上百个档案时就不是这麽容易了。好在 ktlint 也支援自动修正,大多数的问题既然找得出原因就知道该怎麽修正,只要透过 Gradle 执行另一个在 formatting 群组底下的任务 formatKotlin 即可。

> Task :formatKotlinMain
.../ShoppingCart.kt: Format fixed

> Task :formatKotlinTest
.../ShoppingCartTest.kt: Format fixed

> Task :formatKotlin

BUILD SUCCESSFUL in 286ms
2 actionable tasks: 2 executed

ktlint 重新修正程序码排版风格後,应该会看到类似像上面这样的输出。再实际去看档案内容,刚刚被我们故意搞乱的那些程序码通通都回复到原样了,是不是很方便呢?

小结

今天跟大家讨论了如何在专案里导入 ktlint 程序码排版风格检查工具,方便我们在团队合作时统一所有成员的排版风格,还可以帮我们自动修正,维持整个程序码库里的品质。不过,目前我们是在专案里手动执行这些检查,接下来我们就要在 TeamCity 上设定这个检查动作,未来若有成员推 Commit 前没有先通过排版风格检查的话,那 TeamCity 就会自动将该次的 Build 标记为失败,我们就可以即时收到提醒通知,尽早处理和改善喔!

参考资料


<<:  Day02【JS】Event Delegation 事件委派

>>:  Day 18 - Android Studio 如何切换Activity(分页)

Day23 ( 游戏设计 ) 射击幽浮

射击幽浮 教学原文参考:射击幽浮 这篇文章会介绍如何使用「建立游戏角色」、「游戏角色座标」、「游戏角...

[Day 15] Facial Recognition - Eigenfaces

有兴趣知道特徵脸方法 (Eigenfaces)的基本原理 - 主成分分析 (PCA),推荐你看看这...

Day07-Loop

前言 Loop对於程序来说非常非常非常之重要,手动一万次跟电脑做一万次效率差非常多,当然也没有人会去...

Day14 金银满堂-北方名菜合菜戴帽

合菜玳瑁是有名的北方菜,刚好看到读书会书友外带了好吃的合菜戴帽,把合菜戴帽比喻成蛋皮界的星海罗盘让我...

Day5:进入新手村前先让我复习一下QQ-CSS-flexbox-用在外层容器的属性

上一篇讲到的是基本概念的部分,Flexbox可以把它当成一个容器(Container)以及内容物(i...