「Android」用 Spotless 让你的代码 “一尘不染“

Spotless 是什么?

这是一个代码格式化工具,我们可以定义自己想要的代码规则在需要的时候去应用它,整个过程完全自动且可以应用于整个工程。

Spotless 支持多种语言:c、c++、java、kotlin、python 等等更多,应用广泛的开发语言基本都支持。

插件丰富,支持 Gradle、Maven、SBT。并且有 IDE 插件,如:VS Code、Intellij。

社区活跃,很多优秀的开源贡献者,如:ktlint、ktfmt、prittier 等, Github 上的提交经常是几天前。

为什么要用 Spotless?

编写代码时我们都希望遵循固定的代码风格,我们使用的 IDE 也都有代码格式化功能。但是很遗憾,代码格式化都需要开发者手动触发,所以你肯定会有忘记格式化的时候。 如果你的团队有 code review 的过程,你的小伙伴或许能纠正这些问题,当然,也有可能看不到,某段代码就这样”脏“了。

虽然良好、统一的代码风格并不能提高代码性能,即使代码风格很糟糕代码也能正确编译,且运行结果并无二致。但是当你的代码有良好统一风格时,代码会更美观,有更好的阅读性,小伙伴 code review 时可以完全不用关注代码风格。

而 [Spotless](diffplug/spotless: Keep your code spotless (github.com)) 就是这样一个能让你不用关注代码风格的工具,因为它会自动帮你格式化代码。

项目整合

Gradle 配置

首先在 project build.gradle 中添加 Spotless 插件

classpath "com.diffplug.spotless:spotless-plugin-gradle:$spotless_version"

然后在 project 或 module 的 build.gradle 中做如下配置

apply plugin: 'com.diffplug.spotless'
spotless {
    java{
        target 'src/*/java/**/*.java'
        googleJavaFormat()
    }
    kotlin {
        target 'src/*/java/**/*.kt'
        ktlint('0.43.2')
    }

    format 'misc', {
        target '**/*.gradle', '**/*.md', '**/.gitignore'
    }
    format 'xml', {
        target '**/*.xml'
    }

}

结束了,就是这么简单,你需要的仅仅是去配置你想要的代码规则。具体规则配置请参考 [Spotless GitHub](spotless/plugin-gradle at main · diffplug/spotless (github.com))

Java (google-java-format, eclipse jdt, clang-format, prettier, palantir-java-format, formatAnnotations)

Kotlin (ktfmt, ktlint, diktat, prettier)

Spotless gradle task

使用 Spotless 非常简单,一般我们只需要使用两个 task

./gradlew spotlessCheck

执行 spotlessCheck 可以校验代码风格,如果有问题会报错并列出异常代码的位置

./gradlew spotlessApply

执行 spotlessApply 可以在全工程范围内自动修复代码不合规的地方。不过它只能格式化代码,如果规则需要修改代码,比如要删除某个导入的包是需要手动操作的。

从以上两步操作:配置、执行,可以看到 Spotless 的依赖成本是非常低的,使用也非常简单。它带来的好处在我看来有两点:

  • 保证全工程代码风格一致,且是遵循官方代码风格规范
  • 开发者编码阶段完全不需要关心代码风格问题,也不会在 review 阶段花时间更正代码风格,只关注业务价值本身

所以如果你或你的团队在关注代码风格问题,那么 Spotless 一定适合你,请尝试使用吧!

对于 Android 开发最关心的就是 java 和 kotlin 了,这两个语言都有非常多的代码规范支持,不过使用较多的是 Java「google-java-format」kotlin「ktlint」。随着 kotlin 在 Android 开发的占比增长,kotlin 的代码规范就显得更受关注,并且如果你关注 Google 的官方源码,你会发现 Google 的这些工程大多都是使用 ktlint 约束代码风格,这是因为 ktlin 同时支持 official Kotlin coding conventionsAndroid Kotlin Style Guide 两种风格,Android 开发者可以用 ktlint 方便的遵循 Google 代码风格。

更多 ktlint 内容请关注 [ktlint](Ktlint (pinterest.github.io))。

Android Studio lint 插件

前文提到的 google-java-formatktlint 是都有 IDE 插件的,可以在 plugins market 中安装。

个人目前开发比较少涉及到 java ,所以 AS 并没有安装 google-java-format,有 java code format 的开发者可以在市场中安装此工具。下面我简单介绍下 AS ktlint 插件的使用体验。

比如此处多了一个空行,ktlint 会醒目标红,鼠标移过去会展示可操作的选项,可以选择 ktlint format 或禁用此规则。

安装插件后 AS 会增加一个菜单 Refactor -> Format With Ktlint,此菜单可以格式化整个文件,就与 AS 的格式化操作一样,你也可以为 Format With Ktlint 指定快捷键,操作会更方便。

在 ktlint 的 gradle 、AS 插件加持下,相信代码风格在开发中不需要特别花时间去处理了。如果代码风格不正确首先是 AS 的 error 醒目提醒,如果看到了可以一键修复。如果看不到,在执行 ./gradlew spotlessApply之后还可以全工程修复,让“脏”代码无所遁形。

Git hooks

上文介绍的配置,可能已经满足很多人了,不过还是有人会觉得,只要是手动操作的内容,那一定会有可能会忘记,有没有不需要手动操作的格式化操作。 有的有的,方案就是本小结标题 Git hooks。Ktlint 官网有一键安装 git hooks的操作,可以参考 [ktlint git hooks](Command line - Ktlint (pinterest.github.io))。

关于 git hooks 是什么可以参考这篇博文: [git hooks 简介与使用](git hooks 简介与使用 - 简书 (jianshu.com))

不过这个需要每个人都要手动去操作,其实我们可以把 git hooks 脚本文件放到我们工程里,然后通过 gradle 将脚本文件拷贝至 .git 目录

首先在项目下新建hooks目录,新建pre-commit文件:

#!/bin/sh
#
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments.  The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-commit".

./gradlew spotlessCheck
result=$?
printf "the spotlessCheck result code is $result"
if [[ "$result" = 0 ]] ; then
    echo "\033[32m
    ....
    ....
    SpotlessCheck Pass!!
    ....
    ....
    \033[0m"
    exit 0
else
    ./gradlew spotlessApply
    echo "\033[31m
    ....
    ....
    SpotlessCheck Failed!!
    代码格式有问题;
    ....
    已经自动调整格式,review代码后再git add . && git commit
    ....
    ....
    \033[0m"
    exit 1
fi

pre-commit 脚本可以根据自己需要作调整,这边仅仅是一个示例。

下一步需要将此文件拷贝至项目目录下 .git/hooks 目录,可以用 gradle 来处理拷贝事件。

task copyHooks(type: Copy) {
    println 'copyHooks task'
    from("hooks") {
        include "**"
    }
    into ".git/hooks"
}

执行此 task 就可以将项目 hooks 目录内容拷贝至 .git

完成上述操作之后,在每次执行 git commit 之前都会先执行 pre-commit,在校验失败后会自动格式化代码,开发者在 reivew 之后再重新提交。

总结

如果你在开发过程中时不时会因为代码格式化问题造成困扰,那 Spotless 及 ktlint 会完全解放你。让你无需关注代码格式的同时也能保证代码风格的一致。

ktlint 的优秀远不止此篇文中所述,这仅仅是一篇指导文,大家可以去探索更适合自己项目的方法。

希望此文能让大家了解 Spotless 并尝试使用,谢谢!

作者:PuddingSama
链接:https://juejin.cn/post/7187600446902435898

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容