PMDのJavaルールについてまとめます。バージョン6.35.0時のルールとなっています。
非推奨となっているルールには「△」を先頭に付与しています。
バージョン6.35.0から6.47.0までのルールの差分については別の記事でまとめています。 olafnosuke.hatenablog.com
Designカテゴリには、設計上の問題を発見するのに役立つルールが含まれている。
AbstractClassWithoutAnyMethod
抽象クラスにメソッドがない
// NG public abstract class Animal { private String name; } // OK public abstract class Animal { private String name; abstract void doSomething(); }
ルール設定例
<rule ref="category/java/design.xml/AbstractClassWithoutAnyMethod" />
AvoidCatchingGenericException
NullPointerException、RuntimeException、Exceptionのキャッチを避ける
// NG try { } catch (NullPointerException e) { } catch (RuntimeException e) { } catch (Exception e) { }
ルール設定例
<rule ref="category/java/design.xml/AvoidCatchingGenericException" />
AvoidDeeplyNestedIfStmts
深過ぎるif文のネストはしない
// NG int x = 1; int y = 2; int z = 3; if (x > y) { if (y > z) { if (z == x) { } } }
プロパティ
名前 | デフォルト値 | 説明 | 複数指定 |
---|---|---|---|
problemDepth | 3 | if文のネストの閾値 | - |
ルール設定例
<!-- プロパティ設定なし --> <rule ref="category/java/design.xml/AvoidDeeplyNestedIfStmts" /> <!-- プロパティ設定あり --> <rule ref="category/java/design.xml/AvoidDeeplyNestedIfStmts"> <properties> <property name="problemDepth" value="3" /> </properties> </rule>
AvoidRethrowingException
キャッチされた例外を単に再スローしない
// NG try { } catch (RuntimeException e) { throw e; }
ルール設定例
<rule ref="category/java/design.xml/AvoidRethrowingException" />
AvoidThrowingNewInstanceOfSameException
キャッチされた例外と同じ型の新しいインスタンス単を再スローしない
// NG try { } catch (RuntimeException e) { throw new RuntimeException(e); }
ルール設定例
<rule ref="category/java/design.xml/AvoidThrowingNewInstanceOfSameException" />
AvoidThrowingNullPointerException
NullPointerExceptionを手動でスローしない
// NG void doSomething() { throw new NullPointerException(); }
ルール設定例
<rule ref="category/java/design.xml/AvoidThrowingNullPointerException" />
AvoidThrowingRawExceptionTypes
RuntimeException、Throwable、Exception、Errorをthrowしない
// NG void doSomething() { throw new RuntimeException(); }
ルール設定例
<rule ref="category/java/design.xml/AvoidThrowingRawExceptionTypes" />
AvoidUncheckedExceptionsInSignatures
メソッド、コンストラクターのthrows句で非検査例外を明示的に宣言しない
// NG void doSomething() throws RuntimeException { }
ルール設定例
<rule ref="category/java/design.xml/AvoidUncheckedExceptionsInSignatures" />
ClassWithOnlyPrivateConstructorsShouldBeFinal
プライベートコンストラクターのみを持つクラスは final で宣言する
// NG public class Animal { private Animal() { } } // OK public final class Animal { private Animal() { } }
ルール設定例
<rule ref="category/java/design.xml/ClassWithOnlyPrivateConstructorsShouldBeFinal" />
CognitiveComplexity
1 つのメソッド内にあまりにも多くのロジックを含め過ぎない
人間がメソッドを読んで理解することがどれだけ難しいかを示す指標。
制御フローが入れ子になっているとメソッドを理解するのが難しくなるため、制御フローが入れ子になるたびに認知的複雑さが増す。
CognitiveComplexityとは
// if文やループの処理が増えるほど複雑になりすぎる void doSomething() { for (int i = 0; i < 10; i++) { // +1 for (int j = 10; j < 20; j++) { // +1 if (i < 5) { // +2 } else if (j < 15) { // +2 } else if (i == 9 && j == 19) { // +2 } else { // +2 } } } }
プロパティ
名前 | デフォルト値 | 説明 | 複数指定 |
---|---|---|---|
reportLevel | 15 | 複雑さの尺度の検知される閾値 | - |
ルール設定例
<!-- プロパティ設定なし --> <rule ref="category/java/design.xml/CognitiveComplexity" /> <!-- プロパティ設定あり --> <rule ref="category/java/design.xml/CognitiveComplexity"> <properties> <property name="reportLevel" value="15" /> </properties> </rule>
CollapsibleIfStatements
条件式を&&で結合できる二重のifステートメントがないか
// NG int a = 1; int b = 2; if (a < 1) { if (b < 2) { } } // OK int a = 1; int b = 2; if(a < 1 && b < 2){ }
ルール設定例
<rule ref="category/java/design.xml/CollapsibleIfStatements" />
CouplingBetweenObjects
ひとつのオブジェクトの中で使用しているフィールド、ローカル変数、返却値のクラス種類が多すぎないか
プロパティ
名前 | デフォルト値 | 説明 | 複数指定 |
---|---|---|---|
threshold | 20 | 型数の閾値 | - |
ルール設定例
<!-- プロパティ設定なし --> <rule ref="category/java/design.xml/CouplingBetweenObjects" /> <!-- プロパティ設定あり --> <rule ref="category/java/design.xml/CouplingBetweenObjects"> <properties> <property name="threshold" value="20" /> </properties> </rule>
CyclomaticComplexity
メソッドを複雑にしすぎない
メソッド内の決定点の数を数え、メソッドのエントリに1を加えてメソッドの複雑さを評価する。
決定点とは、制御フローがプログラム内の別の場所にジャンプする場所で、if、while、for、case などのすべての制御フロー文が含まれる。
CyclomaticComplexityとは
プロパティ
名前 | デフォルト値 | 説明 | 複数指定 |
---|---|---|---|
classReportLevel | 80 | クラスの複雑度の検出閾値 | - |
methodReportLevel | 10 | メソッドの複雑度の検出閾値 | - |
cycloOptions | Cycloの計算のオプション | 「|」区切り |
ルール設定例
<!-- プロパティ設定なし --> <rule ref="category/java/design.xml/CyclomaticComplexity" /> <!-- プロパティ設定あり --> <rule ref="category/java/design.xml/CyclomaticComplexity"> <properties> <property name="classReportLevel" value="80" /> <property name="methodReportLevel" value="10" /> <property name="cycloOptions" value="" /> </properties> </rule>
DataClass
データクラスかどうか
データクラス:複雑な機能を持たないシンプルなデータホルダー
データクラスはその内部を直接公開することで、カプセル化を破壊し、システムの保守性や理解性を低下させる
//NG public class Animal { public String name = ""; public int age = 0; public int weight = 0; private int hight = 0; public void setHight(int hight) { this.hight = hight; } }
ルール設定例
<rule ref="category/java/design.xml/DataClass" />
DoNotExtendJavaLangError
java.lang.Error をextendしたクラスは定義しない
// NG public class SampleError extends Error { }
ルール設定例
<rule ref="category/java/design.xml/DoNotExtendJavaLangError" />
ExceptionAsFlowControl
例外のスローを複雑にしない
// NG try { try { } catch (IllegalArgumentException e) { throw new RuntimeException(e); } } catch (RuntimeException e) { }
ルール設定例
<rule ref="category/java/design.xml/ExceptionAsFlowControl" />
ExcessiveClassLength
行数が長過ぎるクラスがないか
デフォルトでは1000行を超えると検知される
プロパティ
名前 | デフォルト値 | 説明 | 複数指定 |
---|---|---|---|
minimum | 1000.0 | 行数の最大値 | - |
ルール設定例
<!-- プロパティ設定なし --> <rule ref="category/java/design.xml/ExcessiveClassLength" /> <!-- プロパティ設定あり --> <rule ref="category/java/design.xml/ExcessiveClassLength"> <properties> <property name="minimum" value="1000.0" /> </properties> </rule>
ExcessiveImports
インポートが多過ぎるクラスがないか
デフォルトでは30以上で検知される
プロパティ
名前 | デフォルト値 | 説明 | 複数指定 |
---|---|---|---|
minimum | 30.0 | インポートの最大値 | - |
ルール設定例
<!-- プロパティ設定なし --> <rule ref="category/java/design.xml/ExcessiveImports" /> <!-- プロパティ設定あり --> <rule ref="category/java/design.xml/ExcessiveImports"> <properties> <property name="minimum" value="30.0" /> </properties> </rule>
ExcessiveMethodLength
行数が長すぎるメソッドがないか
デフォルトでは100行を超えると検知される
プロパティ
名前 | デフォルト値 | 説明 | 複数指定 |
---|---|---|---|
minimum | 100.0 | 行数の最大値 | - |
ルール設定例
<!-- プロパティ設定なし --> <rule ref="category/java/design.xml/ExcessiveMethodLength" /> <!-- プロパティ設定あり --> <rule ref="category/java/design.xml/ExcessiveMethodLength"> <properties> <property name="minimum" value="100.0" /> </properties> </rule>
ExcessiveParameterList
メソッドのパラメータ数が多いものがないか
デフォルトでは10以上で検知される
// NG void doSomething(int i, int a, int b, int c, int d, int e, int f, int g, int h, int j) { }
プロパティ
名前 | デフォルト値 | 説明 | 複数指定 |
---|---|---|---|
minimum | 10.0 | パラメータ数の最大値 | - |
ルール設定例
<!-- プロパティ設定なし --> <rule ref="category/java/design.xml/ExcessiveParameterList" /> <!-- プロパティ設定あり --> <rule ref="category/java/design.xml/ExcessiveParameterList"> <properties> <property name="minimum" value="10.0" /> </properties> </rule>
ExcessivePublicCount
多くのpublicメソッド・フィールドが定義されているクラスがないか
デフォルトでは45以上で検知される
プロパティ
名前 | デフォルト値 | 説明 | 複数指定 |
---|---|---|---|
minimum | 45.0 | メソッド・フィールド数の最大値 | - |
ルール設定例
<!-- プロパティ設定なし --> <rule ref="category/java/design.xml/ExcessivePublicCount" /> <!-- プロパティ設定あり --> <rule ref="category/java/design.xml/ExcessivePublicCount"> <properties> <property name="minimum" value="45.0" /> </properties> </rule>
FinalFieldCouldBeStatic
finalフィールドはstaticにする
// NG public final int BAR = 42;
ルール設定例
<rule ref="category/java/design.xml/FinalFieldCouldBeStatic" />
GodClass
ゴッドクラスとなっていないか
ゴッドクラスとは
ルール設定例
<rule ref="category/java/design.xml/GodClass" />
ImmutableField
finalで宣言されていない不変なフィールドがないか
// NG public class Sample { private int number; public Sample() { number = 3; } int doSomething() { return number + 2; } }
プロパティ
名前 | デフォルト値 | 説明 | 複数指定 |
---|---|---|---|
ignoredAnnotations | lombok.Setter| lombok.Getter| lombok.Builder| lombok.Data| lombok.RequiredArgsConstructor| lombok.AllArgsConstructor| lombok.Value| lombok.NoArgsConstructor | このルールで無視するアノテーションの完全修飾名 | 「|」区切り |
ルール設定例
<!-- プロパティ設定なし --> <rule ref="category/java/design.xml/ImmutableField" /> <!-- プロパティ設定あり --> <rule ref="category/java/design.xml/ImmutableField"> <properties> <property name="ignoredAnnotations" value="lombok.Setter|lombok.Getter|lombok.Builder|lombok.Data|lombok.RequiredArgsConstructor|lombok.AllArgsConstructor|lombok.Value|lombok.NoArgsConstructor" /> </properties> </rule>
LawOfDemeter
ルール設定例
<rule ref="category/java/design.xml/LawOfDemeter" />
LogicInversion
式全体を否定するのではなくて反対の演算子を使う
// NG int a = 1; int b = 2; if (!(a == b)) { } // OK int a = 1; int b = 2; if (a != b) { }
ルール設定例
<rule ref="category/java/design.xml/LogicInversion" />
LoosePackageCoupling
指定したパッケージ配下にある許可していないクラスを使用していないか
このルールを適用するためには必ず設定が必要。
<!-- 以下の設定の場合org.springframework.util配下はDigestUtilsのみ使用可能 --> <rule ref="category/java/design.xml/LoosePackageCoupling"> <properties> <property name="packages" value="org.springframework.util" /> <property name="classes" value="DigestUtils" /> </properties> </rule>
// NG import org.springframework.util.StringUtils; public class Sample { void doSomething() { StringUtils.split("", ""); } }
プロパティ
名前 | デフォルト値 | 説明 | 複数指定 |
---|---|---|---|
packages | 制限をつけるパッケージ | 「,」区切り | |
classes | 使用を許可するクラス | 「,」区切り |
ルール設定例
<!-- プロパティ設定あり --> <rule ref="category/java/design.xml/LoosePackageCoupling"> <properties> <property name="packages" value="" /> <property name="classes" value="" /> </properties> </rule>
△ ModifiedCyclomaticComplexity
非推奨のため省略
MutableStaticState
プライベートでないstaticフィールドはfinal と宣言して定数 (または不変参照) にする必要がある
// NG public static Book book = new Book(); // OK public static final Book book = new Book();
ルール設定例
<rule ref="category/java/design.xml/MutableStaticState" />
△ NcssConstructorCount
非推奨のため省略
NcssCount
コメント、空白行を無視し、実際のステートメントのみの行数をカウント
NCSSの計算方法
プロパティ
名前 | デフォルト値 | 説明 | 複数指定 |
---|---|---|---|
methodReportLevel | 60 | NCSSで計算したメソッドの行数の閾値 | - |
classReportLevel | 1500 | NCSSで計算したクラスの行数の閾値 | - |
ncssOptions | 1500 | Ncss の計算のオプション | 「|」区切り |
ルール設定例
<!-- プロパティ設定なし --> <rule ref="category/java/design.xml/NcssCount" /> <!-- プロパティ設定あり --> <rule ref="category/java/design.xml/NcssCount"> <properties> <property name="methodReportLevel" value="60" /> <property name="classReportLevel" value="1500" /> <property name="ncssOptions" value="" /> </properties> </rule>
△ NcssMethodCount
非推奨のため省略
△ NcssTypeCount
非推奨のため省略
NPathComplexity
NPath値を測定し、複雑なメソッドがないか
NPath値の計算
プロパティ
名前 | デフォルト値 | 説明 | 複数指定 |
---|---|---|---|
reportLevel | 200 | NPath値の閾値 | - |
ルール設定例
<!-- プロパティ設定なし --> <rule ref="category/java/design.xml/NPathComplexity" /> <!-- プロパティ設定あり --> <rule ref="category/java/design.xml/NPathComplexity"> <properties> <property name="reportLevel" value="200" /> </properties> </rule>
SignatureDeclareThrowsException
Exceptionをスローするメソッドを検出
// NG // もっと具体的な例外を記述するべき void doSomething() throws Exception { }
プロパティ
名前 | デフォルト値 | 説明 | 複数指定 |
---|---|---|---|
IgnoreJUnitCompletely | false | JUnitのすべてのメソッドが例外をスローできるようにする | - |
ルール設定例
<!-- プロパティ設定なし --> <rule ref="category/java/design.xml/SignatureDeclareThrowsException" /> <!-- プロパティ設定あり --> <rule ref="category/java/design.xml/SignatureDeclareThrowsException"> <properties> <property name="IgnoreJUnitCompletely" value="false" /> </properties> </rule>
SimplifiedTernary
三項演算子でなくても記述できるところを検出
// NG public boolean doSomething() { boolean condition = true; return condition ? true : something(); } // OK public boolean doSomething() { boolean condition = true; return condition || something(); }
ルール設定例
<rule ref="category/java/design.xml/SimplifiedTernary" />
SimplifyBooleanAssertion
assertTrue または assertFalse テストでの否定を避ける
// NG @Test void test() { boolean b = false; assertTrue(!b); } // OK @Test void test() { boolean b = false; assertFalse(b); }
ルール設定例
<rule ref="category/java/design.xml/SimplifyBooleanAssertion" />
SimplifyBooleanExpressions
ブール式での不必要な比較を避ける
// NG public class Sample { private boolean b = (isExist() == true); private boolean isExist() { return false; } } // OK public class Sample { private boolean b = isExist(); private boolean isExist() { return false; } }
ルール設定例
<rule ref="category/java/design.xml/SimplifyBooleanExpressions" />
SimplifyBooleanReturns
booleanを返却するためだけにif..elseステートメントを使わない
// NG private boolean isExist() { int x = 2; int y = 5; if (x == y) { return true; } else { return false; } } // OK private boolean isExist() { int x = 2; int y = 5; return x == y; }
ルール設定例
<rule ref="category/java/design.xml/SimplifyBooleanReturns" />
SimplifyConditional
instanceofの前に不要なnullチェックがないか
// NG void doSomething() { String x = "abc"; if (x != null && x instanceof String) { } } // OK void doSomething() { String x = "abc"; if (x instanceof String) { } }
ルール設定例
<rule ref="category/java/design.xml/SimplifyConditional" />
SingularField
1つのメソッドからしか使用されていないフィールドがないか
// NG public class Sample { private String x; void doSomething(String y) { x = y; } } // OK public class Sample { void doSomething(String y) { String x = y; // ローカル変数にするべき } }
プロパティ
名前 | デフォルト値 | 説明 | 複数指定 |
---|---|---|---|
ignoredAnnotations | lombok.Setter| lombok.Getter| lombok.Builder| lombok.Data| lombok.RequiredArgsConstructor| lombok.AllArgsConstructor| lombok.Value| lombok.NoArgsConstructor| lombok.experimental.Delegate| lombok.EqualsAndHashCode | このルールで無視するアノテーションのの完全修飾名 | 「|」区切り |
checkInnerClasses | false | 内部クラスを確認するか | - |
disallowNotAssignment | false | 最初の使用がアサインメントでない場合、違反を認めない | - |
ルール設定例
<!-- プロパティ設定なし --> <rule ref="category/java/design.xml/SingularField" /> <!-- プロパティ設定あり --> <rule ref="category/java/design.xml/SingularField"> <properties> <property name="ignoredAnnotations" value="lombok.Setter|lombok.Getter|lombok.Builder|lombok.Data|lombok.RequiredArgsConstructor|lombok.AllArgsConstructor|lombok.Value|lombok.NoArgsConstructor|lombok.experimental.Delegate|lombok.EqualsAndHashCode" /> <property name="checkInnerClasses" value="false" /> <property name="disallowNotAssignment" value="false" /> </properties> </rule>
△ StdCyclomaticComplexity
非推奨のため省略
SwitchDensity
switchのケースに対する処理が多すぎないか
プロパティ
名前 | デフォルト値 | 説明 | 複数指定 |
---|---|---|---|
minimum | 10.0 | caseの処理(ステートメント)の最大値 | - |
ルール設定例
<!-- プロパティ設定なし --> <rule ref="category/java/design.xml/SwitchDensity" /> <!-- プロパティ設定あり --> <rule ref="category/java/design.xml/SwitchDensity"> <properties> <property name="minimum" value="10.0" /> </properties> </rule>
TooManyFields
フィールドが多すぎないか
プロパティ
名前 | デフォルト値 | 説明 | 複数指定 |
---|---|---|---|
maxfields | 15 | 最大許容フィールド数 | - |
ルール設定例
<!-- プロパティ設定なし --> <rule ref="category/java/design.xml/TooManyFields" /> <!-- プロパティ設定あり --> <rule ref="category/java/design.xml/TooManyFields"> <properties> <property name="maxfields" value="15" /> </properties> </rule>
TooManyMethods
メソッドが多すぎないか
プロパティ
名前 | デフォルト値 | 説明 | 複数指定 |
---|---|---|---|
maxmethods | 10 | 最大許容メソッド数 | - |
ルール設定例
<!-- プロパティ設定なし --> <rule ref="category/java/design.xml/TooManyMethods" /> <!-- プロパティ設定あり --> <rule ref="category/java/design.xml/TooManyMethods"> <properties> <property name="maxmethods" value="10" /> </properties> </rule>
UselessOverridingMethod
オーバーライドするメソッドがスーパークラスで定義された同じメソッドを呼び出すだけになっていないか
// NG public String toString() { return super.toString(); }
プロパティ
名前 | デフォルト値 | 説明 | 複数指定 |
---|---|---|---|
ignoreAnnotations | false | アノテーションを無視する | - |
ルール設定例
<!-- プロパティ設定なし --> <rule ref="category/java/design.xml/UselessOverridingMethod" /> <!-- プロパティ設定あり --> <rule ref="category/java/design.xml/UselessOverridingMethod"> <properties> <property name="ignoreAnnotations" value="false" /> </properties> </rule>
UseObjectForClearerAPI
publicメソッドで多くの情報を複数の引数として渡す場合、それらすべての情報を表すためにオブジェクトを使用するべき
// NG // 4つの引数をまとめられるクラスを作るべき public void connect(String username, String pssd, String databaseName, String databaseAdress){ }
ルール設定例
<rule ref="category/java/design.xml/UseObjectForClearerAPI" />
UseUtilityClass
staticメソッドしか持たないクラスはユーティリティクラスにすること検討するべき
// NG // ユーティリティクラスとする場合はprivateのコンストラクタを定義する public class Sample { static void doSomething() { } }
プロパティ
名前 | デフォルト値 | 説明 | 複数指定 |
---|---|---|---|
ignoredAnnotations | lombok.experimental.UtilityClass | このルールで無視するアノテーションの完全修飾名 | 「|」区切り |
ルール設定例
<!-- プロパティ設定なし --> <rule ref="category/java/design.xml/UseUtilityClass" /> <!-- プロパティ設定あり --> <rule ref="category/java/design.xml/UseUtilityClass"> <properties> <property name="ignoredAnnotations" value="lombok.experimental.UtilityClass" /> </properties> </rule>
他のカテゴリのルールもまとめています。
Best Practiceカテゴリのまとめはこちら: olafnosuke.hatenablog.com
Code Styleカテゴリのまとめはこちら: olafnosuke.hatenablog.com
Documentationカテゴリのまとめはこちら: olafnosuke.hatenablog.com
Error Proneカテゴリのまとめはこちら: olafnosuke.hatenablog.com
Multithreadingカテゴリのまとめはこちら: olafnosuke.hatenablog.com
Performanceカテゴリのまとめはこちら: olafnosuke.hatenablog.com
Securityカテゴリのまとめはこちら: olafnosuke.hatenablog.com