既存コードへのCheckstyle導入におけるルールの選定

Checkstyle、ずっと導入しようと考えていたのですが、ずっとそのままになっていました。
既存のコードへ導入するのにどういった手順を踏むべきか少し悩んでいたのですが、やっと導入の目処が付けられました。
将来の自分や誰かにとって参考になるかもしれないので、書き残しておきます。
ゴールは「既存のコードに対し、Checkstyleの規則のうち効果的なものを手早く選定して適用すること」です。

自身が導入検討時に使用した環境は以下の通りです。

  • MacOS Mojave
  • IntelliJ IDEA 2019.1
  • Java 8
  • Checkstyle 8.32

Checkstyleとは

Checkstyleは、有名なJavaの静的コード解析ツールの一つ。

今回、静的解析ツールを導入しようと考えた理由は以下の3点です。

  • 静的解析の観点から、プロダクトの品質を上げたり不具合を未然防止したい
  • 「動くルール、仕組み」を実現する。人が読んで守るのではなく、自動でチェックしたい
  • さらにreviewdogと組み合わせて、自動でプルリクレビューを飛ばしたい

また、静的解析ツールの中でもCheckstyleが良いと感じたのは以下の点です。

  • Checkstyleは単体で動作可能
    • MavenやGradleのプラグインを設定しなくてもよいし、設定してもよい
    • 専用のサーバも不要
  • メジャーなので、重要な項目は一通りのカバーできそう
  • reviewdogがcheckstyleフォーマットをサポートしている

なお、静的解析ツールには他にも以下のようなものがあります。

  • SpotBugs:こちらも有名な静的解析ツール。ただしMavenやGradleにプラグイン連携が必要
  • PMD:Checkstyle同様、単体で動作可能。検出項目は一部重複しているが、PMDにしかない項目もある
  • SonarQube:メトリクスの推移を見ることができるが、データ蓄積のためにサーバが必要

項目が多ければ多いほど導入時のチューニングも大変になると思いますし、どれが良いと一概に言えるものではないと思います。
PMDはCheckstyle同様、単体でも動作するのでお手軽ですが、reviewdogとの連携はCheckstyleのほうが容易だと思います。

導入に向けての方針

Checkstyleを既存のコードへ導入するにあたり、以下のことが重要となります。

  • Checkstyleでどのようなルールが存在するかの把握
  • 既存のコードに適したルールのチューニング(取捨選択、設定変更)

Checkstyleの標準的なチェック項目はこちらにかかれていますが、このドキュメントで全部読んでいたらきりがありません。
なので、まずは以下のルールを既存のコードへ適用してみることにします。

これらのルール定義はCheckstyle.jarに同梱されているのですぐに使えますし、実践的なルールが定義されていそうです。
また、名前の通りGoogleやSunのスタイルに由来するものなので、これらをベースにすれば大きな間違いはなさそうです。

なので、以下の方針で調査します。

  1. google_checks.xmlsun_checks.xmlを、それぞれ既存のコードへ適用し、規模感を把握する
  2. 1.の結果から、既存のコードに導入するルールの精査

既存コードにおけるCheckstyleの適用と、検出結果の集計

まずは既存のコードに適用して、どんなルールがどのくらい引っかかるかを試して全体像を把握します。

Checkstyleをダウンロードし、適用するルールとソースコードのディレクトリを指定して実行。

wget https://github.com/checkstyle/checkstyle/releases/download/checkstyle-8.32/checkstyle-8.32-all.jar -O checkstyle.jar
java -jar checkstyle.jar -c /google_checks.xml ./src/main/ -f plain > result.txt
java -jar checkstyle.jar -c /sun_checks.xml ./src/main/ -f plain >> result.txt

そして、各ルールについて引っかかった件数は以下のような感じで抽出して集計。

cat result.txt | sed "s/.*\[/[/g" | grep "^\[" | sort | uniq -c | sort

すると、以下のように表示されます。(※以下はイメージです。実際は約40のルールがそれぞれ1〜1000件程ヒットしました)

   2 [EmptyCatchBlock]
   3 [OneStatementPerLine]
   5 [VariableDeclarationUsageDistance]
   7 [MethodTypeParameterName]
  17 [MissingSwitchDefault]
  32 [FileTabCharacter]
  44 [NeedBraces]
 102 [CommentsIndentation]

これを見て、ざっくり以下のようにルールを選定すれば良さそうだという見込みが立てられました。

  • 件数が多すぎるルール → 開発現場にフィットしない可能性があるので、問題ないことを判断したら除外する
  • 件数が少ないルール → 品質改善に有効な可能性があるので、導入寄りで検討する

ただ、具体的なコードを見ないことには判断できない…ということで、次は具体的にコードを見てルールを精査します。1

既存のコードに導入するルールの精査

集計結果だけでは具体性に欠けるので、各ルールの妥当性が判断できません。
そこで、実際に既存のコードへ適用できそうなルールかどうかはIntelliJ IDEA+プラグインで一つずつ精査します。
検出結果からソースコードへ直接ジャンプできるので、ルール適用の妥当性を判断する際はこちらのほうが効率的です。

IntelliJ IDEA + CheckStyle-IDEAプラグインの準備

IntelliJ IDEAにはCheckstyle用のプラグインがあるので、以下の手順で簡単に使えるようになります。

  1. CheckStyle-IDEAのプラグインを入れる
  2. Checkstyleで使用するルールを設定・選択する
  3. CheckStyleを実行すると、検出結果一覧が表示される
  4. 検出結果一覧にある項目を選択すると、検出されたソースコードの箇所へジャンプできる

ちなみに大抵の場合は検出結果が多すぎるので、google_checks.xmlsun_checks.xmlの中から、有効そうなルールを一つずつ切り出して検証していくのが効率的です。
そして有効そうなルールは本格的な適用に向けて、別のxmlファイルに書き溜めておきます。

ルールの選定基準

選定基準はいろいろあると思いますが、今回は以下のような方針で選定しました。

  • 品質改善に効果がありそうなルールは導入する。誤検知の割合が多いものは除外する
  • 指摘されたときに納得できそうなルールは導入する。好みの色が強いルールや、意見が分かれそうなルールは除外

ルールは合理性が高く、またあるべき姿が明確であるほど、開発チームへ導入するハードルは低くなると考えました。
いきなり完璧なルールを作ろうとするとチームメンバーは付いて来られないので、少しでも共通認識に近いルールを選びました。
意見が分かれそうな項目はCheckstyleが定着してきたら都度議論し、少しずつルールを追加していけば良いと思います。

ルールのサンプル

そして選定したルールのサンプルがこちら

詳細はCheckstyleで汎用的に使えそうなルールをピックアップしてみたにて。

まとめ

というわけで、既存のコードへCheckstyleを導入するときの調査やチューニング方法についてのまとめでした。
Checkstyleも既存コードもあまり把握できていない状況から、どうすればリスクを抑えつつ効果的に導入できるかを考えるのは少し大変でした。
今回はgoogle_checks.xmlsun_checks.xmlの中からルールを精査しましたが、Checkstyleでは他にも循環的複雑度などの計算にも対応しているようです。
折を見て公式のリファレンスを読み、順次適用していきたいと思います。

こういったツールはコードが小規模の段階で導入したほうが、圧倒的に楽だということを強く実感しました…。
初期段階から適用したほうが技術的負債は蓄積されづらいですし、ルールも都度チューニングして育てていくことができると思います。

またCheckstyleに慣れておくと、別のプロジェクトチームに入るときに適用することで品質水準がわかるようになりそうですね。
突然大規模なソースコードを見なければいけなくなったときへの備えとしても、使いこなしておく意味はあると感じました。


  1. もしあまり時間をかけたくないのであれば、数件程度しかヒットしなかったルールに絞って適用してしまうのも一案だと思います。どの程度効果がありそうかは説得力に欠けますが… ↩︎

関連記事


  1. Checkstyleで汎用的に使えそうなルールをピックアップしてみた
  2. JaCoCoでJavaのテストカバレッジのレポートを出力する
  3. 他の人には読めない形式でGitHubのSecretsの値を読み出す
  4. GitHub Actionsでプルリクのコメントに複数行テキストを投稿する
  5. GitHub Actionsでエラーの時だけ特定の処理を実行する
  6. MavenでOSSのライセンス一覧を出力する
  7. アノテーションを活用した影響調査にトライしてみた

comments powered by Disqus