PMD 標準的な ruleset とは何かを調べてみる | Monotalk に続き、
Githubリポジトリから、PMD ルールセットを取得した実装を流用し、
Findbugsの Filterファイルを取得して集計してみました。
集計結果を元に、標準的な findbugs-excludes.xmlを作成してみます。
集計してからわかったこと
Findbugs は exclude 設定のみだと思い込んでいましたが、
include 設定もありました。 幸い集計対象に含めていなかったので、
除外設定としての誤りはないかと思いますので、そのまま結果を記載します。
計測の対象から、include ファイルが漏れているので、そちらのいつか集計したい。。
目次
サンプルの抽出
-
対象プロジェクトはこちらと同様です。
-
上記のリポジトリからファイル名が、以下の名前と一致するものを抽出します。
findbugs-rules.xmlfindbugs-exclude-filter.xmlfindbugs.xmlfindbugs-exclude.xmlfindbugs-filter.xmlexclude.xml
集計方法
-
除外されたルール数をカウントします。
FindbugsがPMDと違う点は、PMDは適用するルールを定義するのに対して、
Findbugsは除外するルールを定義する作りになっています。
このため、どれだけ除外されているかをカウントします。 -
ルールは、
patternと、category、codeにより定義が可能です。
patternが最小単位であるため、category、codeでルールが記述されている場合は、
関連patternを取得して、集計します。
code、categoryとpatternの関係は、findbugs/findbugs.xml at master · findbugsproject/findbugs から、
取得しました。
集計に使用するGithub API
- 集計に使用する
GithubAPIはこちらと同様です。
集計結果
1. Findbugsのルールファイルを保持しているプロジェクト数
- 146/5419 プロジェクト
Findbugsの定義ファイルだけなら、265個 ありました。
1リポジトリに何個もファイルがあったりするので、その重複を排除すると、
146リポジトリで使用されていました。
少なくとも、PMDよりは多くのプロジェクトで使用されているようです。
2. 全体で、除外されているルールの TOP10
| NO | ルール名 | カウント |
|---|---|---|
| 1 | EI_EXPOSE_REP2 | 23 |
| 2 | EI_EXPOSE_REP | 22 |
| 3 | SE_COMPARATOR_SHOULD_BE_SERIALIZABLE | 13 |
| 4 | SE_BAD_FIELD | 11 |
| 5 | DM_DEFAULT_ENCODING | 9 |
| 5 | MS_PKGPROTECT | 9 |
| 7 | MS_MUTABLE_ARRAY | 8 |
| 7 | DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED | 8 |
| 8 | SE_BAD_FIELD_INNER_CLASS | 7 |
| 8 | RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE | 7 |
| 9 | ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD | 6 |
| 9 | DM_EXIT | 6 |
| 9 | SE_NO_SERIALVERSIONID | 6 |
| 9 | PT_RELATIVE_PATH_TRAVERSAL | 6 |
| 9 | JLM_JSR166_UTILCONCURRENT_MONITORENTER | 6 |
| 9 | RV_RETURN_VALUE_IGNORED_BAD_PRACTICE | 6 |
-
全体なので、指定なし[JAVAプロジェクト全体で除外している] ルールのTOP10になります。
-
感覚ベースでの話になりますが、Findbugsについては、行き当たりばったり(バグが検出されたのに応じて。)
除外適用されるルールが多いように思われます。
※超ぱっと見の感覚での話です。 -
全体的に除外しているものは少なく、
クラス指定、メソッド指定などした上で除外することが多いように思われます。
3. クラススコープで除外されているルールの TOP10
続けます。 Class スコープ(正規表現含む)場合の、除外対象 TOP10 になります。
| NO | ルール名 | カウント |
|---|---|---|
| 1 | ALL | 219 |
| 2 | EQ_CHECK_FOR_OPERAND_NOT_COMPATIBLE_WITH_THIS | 195 |
| 3 | EQ_UNUSUAL | 114 |
| 4 | CN_IDIOM_NO_SUPER_CALL | 83 |
| 5 | EI_EXPOSE_REP2 | 80 |
| 6 | SE_NO_SUITABLE_CONSTRUCTOR | 77 |
| 7 | EI_EXPOSE_REP | 68 |
| 8 | BC_UNCONFIRMED_CAST | 62 |
| 9 | DM_DEFAULT_ENCODING | 60 |
| 10 | NM_SAME_SIMPLE_NAME_AS_INTERFACE | 59 |
| 10 | NM_SAME_SIMPLE_NAME_AS_SUPERCLASS | 59 |
-
全体で除外されているものと、傾向は違います。
確かにクラスベースで発生するが、見逃したいバグが除外されているように思います。 -
EI_EXPOSE_REP2とEI_EXPOSE_REPは全体でも、クラスベースでも除外されています。
問題となる場合は、ものすごいわかりにくいバグになると思うのですが、基本除外したい人が多い。 ということでしょうか? -
NM_SAME_SIMPLE_NAME_AS_INTERFACE等はClassならではの除外ルールかもしれません。
4. メソッドスコープで除外されているルールの TOP10
続けます。 Method スコープ(正規表現含む)場合の、除外対象 TOP10 になります。
| NO | ルール名 | カウント |
|---|---|---|
| 1 | DM_EXIT | 40 |
| 2 | NP_BOOLEAN_RETURN_NULL | 23 |
| 2 | EI_EXPOSE_REP | 23 |
| 4 | SF_SWITCH_FALLTHROUGH | 20 |
| 5 | BC_UNCONFIRMED_CAST | 16 |
| 6 | OBL_UNSATISFIED_OBLIGATION | 15 |
| 6 | NP_LOAD_OF_KNOWN_NULL_VALUE | 15 |
| 8 | EI_EXPOSE_REP2 | 14 |
| 9 | REC_CATCH_EXCEPTION | 13 |
| 9 | NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE | 13 |
| 10 | JLM_JSR166_UTILCONCURRENT_MONITORENTER | 12 |
-
確かにメソッドのスコープで除外設定したくなるルールに思われます。
-
NP_BOOLEAN_RETURN_NULLをしたくなるケースってどのような時だろう? と思いました。
True(存在する)orFalse(存在しない)orNull(Unknown) みたいなケースでしょうか?
RDBのようなNullを表現するのに使うんですかね? -
EI_EXPOSE_REP、 とEI_EXPOSE_REP2はジャンル問わず、よくExcludeされていますwww。
5. フィールドスコープで除外されているルールの TOP10
更に続けます。 Field スコープ場合の、除外対象 TOP10 になります。
| NO | ルール名 | カウント |
|---|---|---|
| 1 | IS2_INCONSISTENT_SYNC | 126 |
| 2 | SE_TRANSIENT_FIELD_NOT_RESTORED | 23 |
| 2 | URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD | 23 |
| 4 | SE_BAD_FIELD | 18 |
| 5 | MS_SHOULD_BE_FINAL | 12 |
| 6 | ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD | 9 |
| 7 | EI_EXPOSE_REP2 | 7 |
| 8 | EI_EXPOSE_REP | 6 |
| 8 | UUF_UNUSED_PUBLIC_OR_PROTECTED_FIELD | 6 |
| 8 | MS_PKGPROTECT | 6 |
シリアライズ、や、同期化に関する警告の抑制が多いようです。
-
IS2_INCONSISTENT_SYNCは同期化されていないFieldの場合、出力される警告なので、
問題がある場合と、ない場合があるのだと思います。 -
EI_EXPOSE_REP2、EI_EXPOSE_REPはここでも抑制の対象になっています。
Findbugsルールファイル
以下、ルールで作成しました。
- 各カテゴリの
TOP10を抽出し、重複をマージ
<FindBugsFilter>
<Match>
<Or>
<Bug pattern="BC_UNCONFIRMED_CAST" />
<Bug pattern="CN_IDIOM_NO_SUPER_CALL" />
<Bug pattern="DM_DEFAULT_ENCODING" />
<Bug pattern="DM_EXIT" />
<Bug pattern="DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED" />
<Bug pattern="EI_EXPOSE_REP" />
<Bug pattern="EI_EXPOSE_REP2" />
<Bug pattern="EQ_CHECK_FOR_OPERAND_NOT_COMPATIBLE_WITH_THIS" />
<Bug pattern="EQ_UNUSUAL" />
<Bug pattern="IS2_INCONSISTENT_SYNC" />
<Bug pattern="JLM_JSR166_UTILCONCURRENT_MONITORENTER" />
<Bug pattern="MS_MUTABLE_ARRAY" />
<Bug pattern="MS_PKGPROTECT" />
<Bug pattern="MS_SHOULD_BE_FINAL" />
<Bug pattern="NM_SAME_SIMPLE_NAME_AS_INTERFACE" />
<Bug pattern="NM_SAME_SIMPLE_NAME_AS_SUPERCLASS" />
<Bug pattern="NP_BOOLEAN_RETURN_NULL" />
<Bug pattern="NP_LOAD_OF_KNOWN_NULL_VALUE" />
<Bug pattern="NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE" />
<Bug pattern="OBL_UNSATISFIED_OBLIGATION" />
<Bug pattern="REC_CATCH_EXCEPTION" />
<Bug pattern="SE_BAD_FIELD" />
<Bug pattern="SE_BAD_FIELD_INNER_CLASS" />
<Bug pattern="SE_COMPARATOR_SHOULD_BE_SERIALIZABLE" />
<Bug pattern="SE_NO_SUITABLE_CONSTRUCTOR" />
<Bug pattern="SE_TRANSIENT_FIELD_NOT_RESTORED" />
<Bug pattern="SF_SWITCH_FALLTHROUGH" />
<Bug pattern="ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD" />
<Bug pattern="URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD" />
<Bug pattern="UUF_UNUSED_PUBLIC_OR_PROTECTED_FIELD" />
</Or>
</Match>
</FindBugsFilter>
-
Findbugsの感覚的な使われ方を考えると、乱暴な気はします。
最初かけていなかったけど、途中導入してやたら大量の警告にみまわれる場合で、
ある程度、対象のバグを絞り込みたい場合は、上記のルールを適用しておけばいいのではと考えます。
が、実プロジェクトでうまくいくかどうかは試していないので、わからないです! -
集計詳細はこちらのスプレッドシートに記載しました。
PMD は集計しやすかった。
のに比べて、Findbugs は集計しにくかったのは、定義ファイルの具合にあるのだと思います。
解析のしやすい構造を人書いて設定してもらうのは、
実は設定しにくい? のかもしれません。
以上です。
コメント