PMD 標準的な ruleset とは何かを調べてみる | Monotalk に続き、
Github
リポジトリから、PMD
ルールセットを取得した実装を流用し、
Findbugs
の Filter
ファイルを取得して集計してみました。
集計結果を元に、標準的な findbugs-excludes.xml
を作成してみます。
集計してからわかったこと
Findbugs
は exclude
設定のみだと思い込んでいましたが、
include
設定もありました。 幸い集計対象に含めていなかったので、
除外設定としての誤りはないかと思いますので、そのまま結果を記載します。
計測の対象から、include
ファイルが漏れているので、そちらのいつか集計したい。。
目次
サンプルの抽出
-
対象プロジェクトはこちらと同様です。
-
上記のリポジトリからファイル名が、以下の名前と一致するものを抽出します。
findbugs-rules.xml
findbugs-exclude-filter.xml
findbugs.xml
findbugs-exclude.xml
findbugs-filter.xml
exclude.xml
集計方法
-
除外されたルール数をカウントします。
Findbugs
がPMD
と違う点は、PMD
は適用するルールを定義するのに対して、
Findbugs
は除外するルールを定義する作りになっています。
このため、どれだけ除外されているかをカウントします。 -
ルールは、
pattern
と、category
、code
により定義が可能です。
pattern
が最小単位であるため、category
、code
でルールが記述されている場合は、
関連pattern
を取得して、集計します。
code
、category
とpattern
の関係は、findbugs/findbugs.xml at master · findbugsproject/findbugs から、
取得しました。
集計に使用するGithub API
- 集計に使用する
Github
API
はこちらと同様です。
集計結果
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
(存在する)or
False
(存在しない)or
Null
(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
は集計しにくかったのは、定義ファイルの具合にあるのだと思います。
解析のしやすい構造を人書いて設定してもらうのは、
実は設定しにくい? のかもしれません。
以上です。
コメント