Kengo's blog

Technical articles about original projects, JVM, Static Analysis and TypeScript.

SLF4JのポカミスをPMDで自動検出する

※本記事は昨日世に出た個人プロダクトruleset-for-SLF4Jの宣伝と解説です。


SLF4Jをお使いの方はで有用でコントロールしやすいログを出すための工夫の一貫として、Logger生成時に生成元クラスを渡しているはずです。

private final Logger logger = LoggerFactory.getLogger(Hoge.class);

ここで「いや、こう書くべきだろう」と思った方もきっといらっしゃるでしょう。

private final Logger logger = LoggerFactory.getLogger(getClass());

私もこう書くべきだと思っているひとりです。なぜならコピペ耐性が高いからです(コピペ抑制は諦めてます)。前者の書き方ではコピペが発生した時に正しいLoggerが生成されません。
しかしstaticなLoggerが一般的だったりすでに多様な書き方がリポジトリに行き渡っていたりする場合は、後者に統一することは難しいでしょう。自分自身ポカミスをやらかしますし、そもそも書き方の統一自体が集団開発では難しいものです。


そう、そこでCIですよ。へんちくりんなコードがコミットされたらJenkins大先生に怒っていただくのです。


変なJavaコードを検出すると言えばcheckstyleFindbugsとPMDですが、要件的にPMDかなぁと思ってルールセットを書きました。sonatype社のご好意によりMaven centralにデプロイされているため、ビルドツールから容易に使えるはずです。
例えばMavenなら以下のようにmaven-pmd-pluginを設定してやります。XMLの中身など詳細はREADME.mdを参照してください。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-pmd-plugin</artifactId>
    <version>2.7.1</version>
    <dependencies>
        <dependency>
            <groupId>jp.skypencil</groupId>
            <artifactId>RuleSet-for-SLF4J</artifactId>
            <version>0.1</version>
        </dependency>
    </dependencies>
    <configuration>
        ...
        <rulesets>
            <ruleset>src/rulesets/slf4j.xml</ruleset>
        </rulesets>
    </configuration>
</plugin>

これをPMDプラグインと組み合わせれば先述の「getClass()を使わず、正しくないクラスを渡しているコード」はもちろん、「privateでないLogger」「finalでないLogger」「staticなLogger」を自動的に検出して開発者にフィードバックできます。Jenkinsに限らずgitのhookという手もありますね。


なお本ルールセットはPMD標準のlogging rulesetを補完するようデザインされていますので、そちらもあわせて導入されることをオススメします。特に「Loggerはstaticであるべき」ケースでは、本ルールセットが用意するルールの代わりにLoggerIsNotStaticFinalルールが使用できます。

Sonarユーザなら

Sonarプラグインがありますのでそちらもご利用いただけます。jarファイルはMaven Centralからダウンロードすればいいはずです。

ちなみに

「Loggerがstaticであるべきか否か」は結構面白い議題です。私は基本は非staticでいいだろうと思っていますが、頻繁にインスタンスの生成が行われるクラスではstaticにしたくなる時もあるでしょう。

以上です。自分で作ってなんですが活躍の幅は広いヤツだと思うので、使っていただけるとありがたいです。