AndroidのCustom Lintをチームで運用しよう

# はじめに

この記事は[Recruit Engineers Advent Calendar 2018](https://adventar.org/calendars/3063)の7日目の記事です。

エンジニアとしてAndroidアプリを4年ほど開発しています。
今回は、以前から着手したかったカスタムlintについて書こう！と思いAdvent Calendarにエントリーしたのですが、中々思ったようにまとめれず、運用していくためにどうしたら良いか、ということにフォーカスして記事にまとめることにしました。文字が多いですが、ご容赦ください。

# Android lint

[Android lint](https://developer.android.com/studio/write/lint?hl=ja)は静的解析ツールで、Androidプロジェクトディレクトリにあるソースに対して静的解析を行い、JavaやKotlin、XMLなどのソースコードの品質をチェックしてくれる便利なツールです。

下記のようなコマンドでチェックすることができます。

```
$ lint
もしくは
$ ./gradlew lint
```

デフォルトで様々なチェック項目のルールが用意されていて十分便利です。
ただ、日々の開発でソースコードには追加・修正が行われるもので、それに伴い、デフォルトのルールの以外にも確認したい内容が増えてくると思われます。

そこで、さらに便利に使うために、この静的解析のルールを自分で追加するという方法があります。

* [Writing Custom Lint Rules](http://tools.android.com/tips/lint-custom-rules)

実際に利用することを考えた場合、そのカスタムルールを作るために事前知識も多く必要で、その生成コストも無視できるものではなく、特に、チーム開発していると運用までの障壁が高いと感じました。

今回は、自分たちのチームでカスタムlintを運用していくために必要だと考えていることをまとめてみました。
あくまで、「自分たちのチーム」で運用するためであり、ライブラリとして外部に公開する前提のものではないことは念頭に置いておいてください。

# カスタムlintを運用していくためにどうすれば良いか

## いつlintを実行させるか決める

まずはlintを実行するタイミングを決めるべきです。せっかく定義したルールも、各自の良きタイミングで見るということになると、保守されず廃れていって、そのうち消えることとなります。
一般的な実行タイミングとしては、Gitでマージリクエストを送るタイミングではないでしょうか。

## 差分だけを確認するようにする

ここの話はカスタムlintの話というより、lintを導入した際のお話です。
最初にlintを確認する運用をプロジェクトに入れた際、これまでチェックしていなかった指摘をlintからされる場合があります。
自分もあるプロジェクトに初めてlintを導入してみると、その指摘数が数百になったこともありました。
もちろん、一気に解消できるのであればそれがベストですが、それら全部の指摘を一気に解消しようとすると、コストがかかりすぎる場合もあると思います。

その場合は、指摘には一通り目を通して、「今すぐ対応すべき指摘」と「あとで対応する指摘」に分け、「今すぐ対応すべき指摘」は修正し、「あとで対応する指摘」は次にソースコードを修正するときに一緒に修正することがおすすめです。

そのように判断したときに役立つのが[danger-android_lint](https://github.com/loadsmart/danger-android_lint)です。
[danger-android_lint#lint-only-addedmodified-files](https://github.com/loadsmart/danger-android_lint#lint-only-addedmodified-files)にあるように、差分だけを指摘してくれる機能があります。便利。

## カスタムlintを作ることにこだわり過ぎない

開発していると、今後も守っていきたいコーディングルールなどが出てくると思いますが、そのルールのカスタムlintを作ることにこだわり過ぎないことも重要です。
カスタムlintを作るのに工数かけたわりに、チェックすることが少なく、費用対効果が薄いというパターンや、
初めに着手したルールが複雑すぎて、挫折してしまうパターンが考えられるからです。

なので、まずはできることからやるように、チームのスキルや状況によって判断すべきです。カスタムlintで定義することを一度諦める判断も取るべきだと思います。

ただ、そういったものは後々の人力での確認が厳しくなったタイミング、または、実装方法がわかったタイミングなどで、カスタムlintを定義するように再考慮するようにしたら良い思います。

## すべてのカスタムlintの実装方法を一気に覚えようとしない

チェックしたい内容を検知するためにDetectorクラスがありますが、ここが一番覚える内容が多いです。
すべてを一気に覚えるのは難しいと思います。
なので、まずは簡単なものから着手していって、徐々に難しいものを覚えていきましょう。
（本当はここをリッチに書きたかったけど、時間が足りずに諦めました。。）

## Issueクラスに定義する内容に制約を設ける

詳細な説明は他記事を参照してほしいのですが、Issueクラスはlintの各指摘内容のリファレンスのようなものです。
このIssueで定義する項目の中には、基準がよくわからないものもあります。
例えば、Priority（優先度）はやSeverity（重要度）です。
どうなったらPriorityが8になって、どこからがSeverityがErrorになるのか、ということは判断しづらいです。
そこで、あくまで自チームでの運用だけを考えるた場合、これらの定義内容を限定的にして、書きやすくできると思います。
というのも、チームとしてルールを追加したいとした指摘って、基本は優先度も重要度も高いはずだから、ほぼ値も変わらないはずです。

先程の例だと、下記のように定義しても良いと思います。

* Priorityは8で固定にする
* SeverityはWarningで固定にする

## Registryクラスは一つだけ

RegistryクラスはIssueクラスの一覧を登録して置くもので、プロジェクトからそのRegistryクラスを参照してあげる必要があります。
このRegistryクラスは他のプロジェクトで再利用することもなく、複数用意して毎回プロジェクトに設定するのも手間なので、プロジェクトで共通のRegistryクラスを作って、そこにIssueクラスを追加することで問題ないと思います。

## 運用のフェーズではチームみんなでやる

導入するためには、カスタムlintのための開発環境の整備であったり、ルールを決めたりやることが多いと思います。
そこは担当者が主体性をもって推進するのは良いですか、実際に運用するフェーズに入ったら、みんなで取り組むように意識するべきです。
担当者だけで運用することなった場合、そこがボトルネックとなってスムーズな運用もできず、カスタムlintのルールの拡張も進まないと思います。

# さいごに

今回はチームでカスタムlintを運用していくために必要だと考えていることをまとめてみました。
こんな感じで運用を回していきたいです。

また、今回書けなかった詳細な実装のサンプルなどは、別記事で気力があればまとめたいと思います。

# 役に立った参考リンク

* http://tools.android.com/tips/lint-custom-rules
* https://qiita.com/hotchemi/items/9364d54a0e024a5e6275
* [danger-android_lint](https://github.com/loadsmart/danger-android_lint)