Spring Boot + npm + Geb で入力フォームを作ってテストする ( その55 )( PMD を 5.8.1 → 6.4.0 へバージョンアップする )
概要
記事一覧はこちらです。
Spring Boot + npm + Geb で入力フォームを作ってテストする ( その54 )( webpack を 3.8.1 → 4.9.1 へバージョンアップする ) の続きです。
- 今回の手順で確認できるのは以下の内容です。
参照したサイト・書籍
PMD Release Notes - 15-December-2017 - 6.0.0
https://pmd.github.io/pmd-6.0.0/pmd_release_notes.html#metrics-frameworkPMD Making Rulesets
https://pmd.github.io/pmd-6.4.0/pmd_userdocs_making_rulesets.htmlJava Rules
https://pmd.github.io/pmd-6.4.0/pmd_rules_java.html
目次
- build.gradle を変更する
- 変更の方針を決める
- category/java/bestpractices.xml
Unsupported build listener: class org.gradle.api.internal.project.ant.AntLoggingAdapter
、Unsupported build listener: class org.apache.tools.ant.AntClassLoader
This analysis could be faster, please consider using Incremental Analysis: https://pmd.github.io/pmd-6.4.0/pmd_userdocs_getting_started.html#incremental-analysis
- category/java/codestyle.xml
Variables that are final and static should be all capitals, '...' is not all capitals.
Parameter '...' is not assigned and could be declared final
Avoid excessively long variable names like ...
Local variable '...' could be declared final
Each class should declare at least one constructor
Avoid variables with short names like ...
Avoid the use of value in annotations when its the only element
Avoid unnecessary constructors - the compiler will generate these for you
The utility class name '...' doesn't match '[A-Z][a-zA-Z0-9]+(Utils?|Helper)'
Use explicit scoping instead of the default package private level
To avoid mistakes add a comment at the beginning of the ... field if you want a default access modifier
A method should have only one exit point, and that should be the last statement in the method
- category/java/design.xml
Removed misconfigured rule: LoosePackageCoupling cause: No packages or classes specified
All methods are static. Consider using a utility class instead. Alternatively, you could add a private constructor or make the class abstract to silence this warning.
The method '...' has a NCSS line count of ....
Potential violation of Law of Demeter (method chain calls)
This class has too many methods, consider refactoring it.
The class '...' is suspected to be a Data Class
Avoid throwing raw exception types.
Rather than using a lot of String arguments, consider using a container object for those values.
The method '...' has a cyclomatic complexity of ....
- ここまでやってみた感想
手順
build.gradle を変更する
build.gradle の以下の点を変更します。
pmd { toolVersion = "6.4.0" sourceSets = [project.sourceSets.main] ignoreFailures = true consoleOutput = true ruleSetFiles = rootProject.files("/config/pmd/pmd-project-rulesets.xml") ruleSets = [] }
toolVersion = "5.8.1"
→toolVersion = "6.4.0"
に変更します。
変更後、Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。
clean タスク実行 → Rebuild Project 実行 → build タスクを実行してみますが、相変わらず大量にエラーが出ています。。。
変更の方針を決める
PMD Release Notes - 15-December-2017 - 6.0.0、PMD Making Rulesets、Java Rules を見ると、Rule の Category が一新されていて1から見直した方が良さそうに思えたので、以下の方針で変更します。
- pmd-project-rulesets.xml は1から作り直します。build タスク実行で出力されたエラーメッセージを元に修正はしません。
- pmd-project-rulesets.xml には
<rule ref="category/java/bestpractices.xml" />
のフォーマットで Category の xml ファイルを1つずつ記述して、build タスクを実行して結果を見て調整します。 - 現在 exclude している Rule は、基本的に同じように exclude します。
config/pmd/pmd-project-rulesets.xml を以下の内容に書き換えます。
<?xml version="1.0" encoding="UTF-8"?> <ruleset name="mybraces" xmlns="http://pmd.sourceforge.net/ruleset/2.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd"> <description>project rulesets</description> <!-- rulesets の種類・説明は 以下の URL 参照 https://github.com/pmd/pmd/tree/master/pmd-java/src/main/resources/category/java https://github.com/pmd/pmd/tree/master/pmd-java/src/main/resources/rulesets/java https://pmd.github.io/pmd-6.4.0/pmd_rules_java.html ※"pmd-6.4.0" の部分は適用しているバージョンに変更すること。 --> <rule ref="category/java/bestpractices.xml"/> .......... </ruleset>
<rule ref="category/java/bestpractices.xml"/>
の部分に1つずつ category を記述して調整していきます。
category/java/bestpractices.xml
PMD のルール違反は出ませんでしたが、それ以外で以下のメッセージが出力されました。
:pmdMain Unsupported build listener: class org.gradle.api.internal.project.ant.AntLoggingAdapter Unsupported build listener: class org.apache.tools.ant.AntClassLoader This analysis could be faster, please consider using Incremental Analysis: https://pmd.github.io/pmd-6.4.0/pmd_userdocs_getting_started.html#incremental-analysis This analysis could be faster, please consider using Incremental Analysis: https://pmd.github.io/pmd-6.4.0/pmd_userdocs_getting_started.html#incremental-analysis
Unsupported build listener: class org.gradle.api.internal.project.ant.AntLoggingAdapter
、Unsupported build listener: class org.apache.tools.ant.AntClassLoader
コマンドラインから gradlew clean
→ gradlew --debug pmdMain
を実行してみたところ、以下のログが出力されました。
16:06:18.934 [WARN] [org.gradle.api.internal.project.ant.AntLoggingAdapter] Unsupported build listener: class org.gradle.api.internal.project.ant.AntLoggingAdapter 16:06:18.935 [WARN] [org.gradle.api.internal.project.ant.AntLoggingAdapter] Unsupported build listener: class org.apache.tools.ant.AntClassLoader
Unsupported build listener
で調べてみると
Gradle - Method details - addBuildListener) から Interface BuildListener が見つかりました。AntLoggingAdapter と AntClassLoader のクラスで BuildListener インターフェースが実装されていないのが原因のようです。
WARN のログなので、出力されたままにすることにします。
This analysis could be faster, please consider using Incremental Analysis: https://pmd.github.io/pmd-6.4.0/pmd_userdocs_getting_started.html#incremental-analysis
https://pmd.github.io/pmd-6.4.0/pmd_userdocs_getting_started.html#incremental-analysis のリンク先のページを見ると、なぜか Gradle だけリンクになっていませんね。。。
他にも調べてみると Revert "Support PMD's analysis cache (#2223)" が見つかりました。おそらく原因はこれだと思うのですが、まだ解決していないようです。対策がないようですので、出力されたままにします。
category/java/codestyle.xml
設定を追加して build タスクを実行すると 307 PMD rule violations were found.
と出力されました。メッセージは以下の12種類でした。
Variables that are final and static should be all capitals, '...' is not all capitals.
Parameter '...' is not assigned and could be declared final
Avoid excessively long variable names like ...
Local variable '...' could be declared final
Each class should declare at least one constructor
Avoid variables with short names like ...
Avoid the use of value in annotations when its the only element
Avoid unnecessary constructors - the compiler will generate these for you
The utility class name '...' doesn't match '[A-Z][a-zA-Z0-9]+(Utils?|Helper)'
Use explicit scoping instead of the default package private level
To avoid mistakes add a comment at the beginning of the ... field if you want a default access modifier
A method should have only one exit point, and that should be the last statement in the method
Variables that are final and static should be all capitals, '...' is not all capitals.
VariableNamingConventions のルール違反のメッセージです。前も exclude していたので、今回も exclude します。
Parameter '...' is not assigned and could be declared final
MethodArgumentCouldBeFinal のルール違反のメッセージです。前も exclude していたので、今回も exclude します。
Avoid excessively long variable names like ...
LongVariable のルール違反のメッセージです。前も exclude していたので、今回も exclude します。
Local variable '...' could be declared final
LocalVariableCouldBeFinal のルール違反のメッセージです。前も exclude していたので、今回も exclude します。
Each class should declare at least one constructor
AtLeastOneConstructor のルール違反のメッセージです。前は何もしていませんでしたが、今のところ対応する必要性を感じなかったので exclude します。
Avoid variables with short names like ...
ShortVariable のルール違反のメッセージです。前も exclude していたので、今回も exclude します。
Avoid the use of value in annotations when its the only element
UnnecessaryAnnotationValueElement のルール違反のメッセージです。PMD 6.2.0 から新規に追加された Rule です。指摘された箇所のアノテーションは削除しようがなかったので、exclude します。
Avoid unnecessary constructors - the compiler will generate these for you
UnnecessaryConstructor のルール違反のメッセージです。
メッセージが出ているのは src/main/java/ksbysample/webapp/bootnpmgeb/config/DomaConfig.java で、ルール違反を指摘されているコンストラクタを削除しても特に問題なかったので、ソースを修正してメッセージが出ないようにします。
The utility class name '...' doesn't match '[A-Z][a-zA-Z0-9]+(Utils?|Helper)'
ClassNamingConventions のルール違反のメッセージです。
メッセージが出ているのは以下の2つのクラスですが、static のフィールド・メソッドしかないと出ているようです。
- src/main/java/ksbysample/webapp/bootnpmgeb/constants/UrlConst.java
- src/main/java/ksbysample/webapp/bootnpmgeb/util/validator/EmailValidator.java
個人的にクラス名を変更したくなかったので、exclude することにします。
Use explicit scoping instead of the default package private level
DefaultPackage のルール違反のメッセージです。
メッセージが出ているのは Doma 2 の Entity クラスで対応しようがなかったので、exclude することにします。
To avoid mistakes add a comment at the beginning of the ... field if you want a default access modifier
CommentDefaultAccessModifier のルール違反のメッセージです。
メッセージが出ているのは Doma 2 の Entity クラスで、DomaGen で生成した時にコメントがついていないのが原因なので(確か COMMENT ON COLUMN ... IS '...';
でカラムにコメントを付けるとコメントに出るはず)、exclude することにします。
A method should have only one exit point, and that should be the last statement in the method
OnlyOneReturn のルール違反のメッセージです。
個人的にはメソッド内に複数 return を入れても構わないと思っているので、exclude します。
以上で category/java/codestyle.xml は以下のような定義になりました。
<rule ref="category/java/codestyle.xml"> <exclude name="VariableNamingConventions"/> <exclude name="MethodArgumentCouldBeFinal"/> <exclude name="LongVariable"/> <exclude name="LocalVariableCouldBeFinal"/> <exclude name="AtLeastOneConstructor"/> <exclude name="ShortVariable"/> <exclude name="UnnecessaryAnnotationValueElement"/> <exclude name="ClassNamingConventions"/> <exclude name="DefaultPackage"/> <exclude name="CommentDefaultAccessModifier"/> <exclude name="OnlyOneReturn"/> </rule>
category/java/design.xml
設定を追加して build タスクを実行すると 95 PMD rule violations were found.
と出力されました。メッセージは以下の9種類でした。
Removed misconfigured rule: LoosePackageCoupling cause: No packages or classes specified
All methods are static. Consider using a utility class instead. Alternatively, you could add a private constructor or make the class abstract to silence this warning.
The method '...' has a NCSS line count of ....
Potential violation of Law of Demeter (method chain calls)
This class has too many methods, consider refactoring it.
The class '...' is suspected to be a Data Class
Avoid throwing raw exception types.
Rather than using a lot of String arguments, consider using a container object for those values.
The method '...' has a cyclomatic complexity of ....
Removed misconfigured rule: LoosePackageCoupling cause: No packages or classes specified
LoosePackageCoupling の設定がないというメッセージのようです。
リンク先の説明を読みましたが、今は必要そうに思えなかったので exclude することにします。
All methods are static. Consider using a utility class instead. Alternatively, you could add a private constructor or make the class abstract to silence this warning.
UseUtilityClass のルール違反のメッセージです。
ClassNamingConventions を exclude したのと同じ理由で、こちらも exclude します。
The method '...' has a NCSS line count of ....
NcssCount のルール違反のメッセージです。PMD 6.0.0 から新規に追加された Rule です。
実はこのルールが何を指摘しているのかよく分かりませんでした。。。 対応方法もよく分からないので exclude します。
Potential violation of Law of Demeter (method chain calls)
LawOfDemeter のルール違反のメッセージです。
リンク先の説明を読みましたが、有効性がよく分からなかったので exclude します。
This class has too many methods, consider refactoring it.
TooManyMethods のルール違反のメッセージです。
このルールは残しておきたいので、メッセージが表示された以下のクラスに @SuppressWarnings("PMD.TooManyMethods")
を付けることにします。
The class '...' is suspected to be a Data Class
DataClass のルール違反のメッセージです。PMD 6.0.0 から新規に追加された Rule です。
メッセージが出ていたのが Doma 2 の Entity クラスだったのですが対応のしようがないのと、このルールの必要性も感じなかったので、exclude します。
Avoid throwing raw exception types.
AvoidThrowingRawExceptionTypes のルール違反のメッセージです。
エラーが明確に分かる例外クラスではなく RuntimeException を throw していたところでメッセージが出ていました。確かにその通りなので、今回はメッセージが出ている以下のクラスに @SuppressWarnings("PMD.AvoidThrowingRawExceptionTypes")
を付けることにします。
- src/main/java/ksbysample/webapp/bootnpmgeb/helper/freemarker/FreeMarkerHelper.java
- src/main/java/ksbysample/webapp/bootnpmgeb/values/ValuesHelper.java
- src/main/java/ksbysample/webapp/bootnpmgeb/values/validation/ValuesEnumValidator.java
Rather than using a lot of String arguments, consider using a container object for those values.
UseObjectForClearerAPI のルール違反のメッセージです。
メソッドの引数が多い場合に Parameter クラスを新規作成してそちらでも渡せるようにした方がよい、というルールのようです。今のところ必要性を感じなかったので exclude します。
The method '...' has a cyclomatic complexity of ....
CyclomaticComplexity のルール違反のメッセージです。
1メソッド内の行数(処理量?)が多いと出るメッセージで有効だと思うのですが、今回は exclude します。
以上で category/java/codestyle.xml は以下のような定義になりました。
<rule ref="category/java/design.xml"> <exclude name="LoosePackageCoupling"/> <exclude name="UseUtilityClass"/> <exclude name="NcssCount"/> <exclude name="LawOfDemeter"/> <exclude name="DataClass"/> <exclude name="UseObjectForClearerAPI"/> <exclude name="CyclomaticComplexity"/> </rule>
ここまでやってみた感想
今回は Rule の exclude 有無を1つずつ見直していますが、単純にバージョンアップするなら以下の方針で構わないと思います。
- build.gradle の記述については特に変更する必要はありません。
- 独自の Rulesets は書き方が変わっているので書き直しが必要。https://github.com/pmd/pmd/tree/master/pmd-java/src/main/resources/category/java の category の一覧を見て、xml ファイルに
<rule ref="category/java/bestpractices.xml"/>
のフォーマットで全て列挙します。 - その後に build タスクを実行して、メッセージが出力された Rule を全て exclude します。
- 6 以降に追加された Rule は exclude されたままにせず確認して追加するのか exclude したままにするのか判断します。
履歴
2018/06/03
初版発行。