コンテンツにスキップ

2025年4月26日

今週の活動

リファクタリングについての理解を深める

  • リファクタリング 既存のコードを安全に改善するの第2章まで読んだ
  • 第1章「リファクタリング - 最初の例」
    • サンプルコードを通してリファクタリングの具体的な手順を知る
  • 第2章「リファクタリングの原則」
    • リファクタリングの定義、リファクタリングのタイミング、リファクタリングの問題点、リファクタリングをソフトウェア開発プロセスに組み込む方法を知る

Checkstyleのインストール

Mavenを使用する場合

  • Qualitas Corpusのディレクトリに移動
  • mvn archetype:generate -DgroupId=com.example -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=falseを実行
  • my-appディレクトリ配下のディレクトリとファイルをカレントディレクトリに移動し、my-appディレクトリを削除
    • mv my-app/* .
    • rmdir my-app
  • pom.xmlのpluginタグ内に以下のコードを追加
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-checkstyle-plugin</artifactId>
    <version>3.6.0</version>
    <configuration>
      <configLocation>checkstyle/checkstyle.xml</configLocation>
    </configuration>
    
  • Checkstykeのルールセットファイルを作成
    • mkdir checkstyle
    • touch checkstyle/checkstyle.xml
  • CheckstyleはデフォルトではSun Microsystemsの定義を使用するため、その設定をcheckstyle.xmlに明示的に書き込む
    • https://github.com/checkstyle/checkstyle/blob/main/src/main/resources/sun_checks.xml
      <?xml version="1.0"?>
      <!DOCTYPE module PUBLIC
                "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
                "https://checkstyle.org/dtds/configuration_1_3.dtd">
      
      <!--
      
        Checkstyle configuration that checks the sun coding conventions from:
      
          - the Java Language Specification at
            https://docs.oracle.com/javase/specs/jls/se11/html/index.html
      
          - the Sun Code Conventions at https://www.oracle.com/java/technologies/javase/codeconventions-contents.html
      
          - the Javadoc guidelines at
            https://www.oracle.com/technical-resources/articles/java/javadoc-tool.html
      
          - the JDK Api documentation https://docs.oracle.com/en/java/javase/11/
      
          - some best practices
      
        Checkstyle is very configurable. Be sure to read the documentation at
        https://checkstyle.org (or in your downloaded distribution).
      
        Most Checks are configurable, be sure to consult the documentation.
      
        To completely disable a check, just comment it out or delete it from the file.
        To suppress certain violations please review suppression filters.
      
        Finally, it is worth reading the documentation.
      
      -->
      
      <module name="Checker">
        <!--
            If you set the basedir property below, then all reported file
            names will be relative to the specified directory. See
            https://checkstyle.org/config.html#Checker
      
            <property name="basedir" value="${basedir}"/>
        -->
        <property name="severity" value="error"/>
      
        <property name="fileExtensions" value="java, properties, xml"/>
      
        <!-- Excludes all 'module-info.java' files              -->
        <!-- See https://checkstyle.org/filefilters/index.html -->
        <module name="BeforeExecutionExclusionFileFilter">
          <property name="fileNamePattern" value="module\-info\.java$"/>
        </module>
      
        <!-- https://checkstyle.org/filters/suppressionfilter.html -->
        <module name="SuppressionFilter">
          <property name="file" value="${org.checkstyle.sun.suppressionfilter.config}"
                    default="checkstyle-suppressions.xml" />
          <property name="optional" value="true"/>
        </module>
      
        <!-- Checks that a package-info.java file exists for each package.     -->
        <!-- See https://checkstyle.org/checks/javadoc/javadocpackage.html#JavadocPackage -->
        <module name="JavadocPackage"/>
      
        <!-- Checks whether files end with a new line.                        -->
        <!-- See https://checkstyle.org/checks/misc/newlineatendoffile.html -->
        <module name="NewlineAtEndOfFile"/>
      
        <!-- Checks that property files contain the same keys.         -->
        <!-- See https://checkstyle.org/checks/misc/translation.html -->
        <module name="Translation"/>
      
        <!-- Checks for Size Violations.                    -->
        <!-- See https://checkstyle.org/checks/sizes/index.html -->
        <module name="FileLength"/>
        <module name="LineLength">
          <property name="fileExtensions" value="java"/>
        </module>
      
        <!-- Checks for whitespace                               -->
        <!-- See https://checkstyle.org/checks/whitespace/index.html -->
        <module name="FileTabCharacter"/>
      
        <!-- Miscellaneous other checks.                   -->
        <!-- See https://checkstyle.org/checks/misc/index.html -->
        <module name="RegexpSingleline">
          <property name="format" value="\s+$"/>
          <property name="minimum" value="0"/>
          <property name="maximum" value="0"/>
          <property name="message" value="Line has trailing spaces."/>
        </module>
      
        <!-- Checks for Headers                                -->
        <!-- See https://checkstyle.org/checks/header/index.html   -->
        <!-- <module name="Header"> -->
        <!--   <property name="headerFile" value="${checkstyle.header.file}"/> -->
        <!--   <property name="fileExtensions" value="java"/> -->
        <!-- </module> -->
      
        <module name="TreeWalker">
      
          <!-- Checks for Javadoc comments.                     -->
          <!-- See https://checkstyle.org/checks/javadoc/index.html -->
          <module name="InvalidJavadocPosition"/>
          <module name="JavadocMethod"/>
          <module name="JavadocType"/>
          <module name="JavadocVariable"/>
          <module name="JavadocStyle"/>
          <module name="MissingJavadocMethod"/>
      
          <!-- Checks for Naming Conventions.                  -->
          <!-- See https://checkstyle.org/checks/naming/index.html -->
          <module name="ConstantName"/>
          <module name="LocalFinalVariableName"/>
          <module name="LocalVariableName"/>
          <module name="MemberName"/>
          <module name="MethodName"/>
          <module name="PackageName"/>
          <module name="ParameterName"/>
          <module name="StaticVariableName"/>
          <module name="TypeName"/>
      
          <!-- Checks for imports                              -->
          <!-- See https://checkstyle.org/checks/imports/index.html -->
          <module name="AvoidStarImport"/>
          <module name="IllegalImport"/> <!-- defaults to sun.* packages -->
          <module name="RedundantImport"/>
          <module name="UnusedImports">
            <property name="processJavadoc" value="false"/>
          </module>
      
          <!-- Checks for Size Violations.                    -->
          <!-- See https://checkstyle.org/checks/sizes/index.html -->
          <module name="MethodLength"/>
          <module name="ParameterNumber"/>
      
          <!-- Checks for whitespace                               -->
          <!-- See https://checkstyle.org/checks/whitespace/index.html -->
          <module name="EmptyForIteratorPad"/>
          <module name="GenericWhitespace"/>
          <module name="MethodParamPad"/>
          <module name="NoWhitespaceAfter"/>
          <module name="NoWhitespaceBefore"/>
          <module name="OperatorWrap"/>
          <module name="ParenPad"/>
          <module name="TypecastParenPad"/>
          <module name="WhitespaceAfter"/>
          <module name="WhitespaceAround"/>
      
          <!-- Modifier Checks                                    -->
          <!-- See https://checkstyle.org/checks/modifier/index.html -->
          <module name="ModifierOrder"/>
          <module name="RedundantModifier"/>
      
          <!-- Checks for blocks. You know, those {}'s         -->
          <!-- See https://checkstyle.org/checks/blocks/index.html -->
          <module name="AvoidNestedBlocks"/>
          <module name="EmptyBlock"/>
          <module name="LeftCurly"/>
          <module name="NeedBraces"/>
          <module name="RightCurly"/>
      
          <!-- Checks for common coding problems               -->
          <!-- See https://checkstyle.org/checks/coding/index.html -->
          <module name="EmptyStatement"/>
          <module name="EqualsHashCode"/>
          <module name="HiddenField"/>
          <module name="IllegalInstantiation"/>
          <module name="InnerAssignment"/>
          <module name="MagicNumber"/>
          <module name="MissingSwitchDefault"/>
          <module name="MultipleVariableDeclarations"/>
          <module name="SimplifyBooleanExpression"/>
          <module name="SimplifyBooleanReturn"/>
      
          <!-- Checks for class design                         -->
          <!-- See https://checkstyle.org/checks/design/index.html -->
          <module name="DesignForExtension"/>
          <module name="FinalClass"/>
          <module name="HideUtilityClassConstructor"/>
          <module name="InterfaceIsType"/>
          <module name="VisibilityModifier"/>
      
          <!-- Miscellaneous other checks.                   -->
          <!-- See https://checkstyle.org/checks/misc/index.html -->
          <module name="ArrayTypeStyle"/>
          <module name="FinalParameters"/>
          <module name="TodoComment"/>
          <module name="UpperEll"/>
      
          <!-- https://checkstyle.org/filters/suppressionxpathfilter.html -->
          <module name="SuppressionXpathFilter">
            <property name="file" value="${org.checkstyle.sun.suppressionxpathfilter.config}"
                      default="checkstyle-xpath-suppressions.xml" />
            <property name="optional" value="true"/>
          </module>
      
        </module>
      
      </module>
      
  • 自動生成されたApp.javaファイルを削除
  • 必要に応じて、Qualitas CorpusにあるSystems/<システム名>/<システムのバージョン>/srcディレクトリをsrc/main/java/com/exampleディレクトリにコピー
    • 例: cp -r Systems/ant/ant-1.8.4/src/apache-ant-1.8.4/src/main/ src/main/java/com/example/
  • mvn checkstyle:checkコマンドを実行 - このコマンドは、デフォルトではsrc/main/javaディレクトリ以下のJavaファイルを解析 - このコマンドを実行すると、解析結果がtargetディレクトリに出力される - 注意点 - 解析対象のシステムで使用されているJavaのバージョンが非常に古い場合は、解析時にエラーが起きる

SonarQubeのインストール

SonarQubeサーバーのインストール

MacOSを使用する場合
  • ダウンロードページからCommunity Buildをダウンロード
  • ダウンロードしたzipファイルを解凍
  • /opt配下にSonarQube用のディレクトリを作成
    • sudo mkdir /opt/sonarqube
  • /opt/sonarqubeにSonarQubeプロジェクトを移動
    • sudo mv ~/Downloads/sonarqube-25.4.0.105899 /opt/sonarqube/
  • bin/macosx-universal-64/sonar.shを実行
    • /opt/sonarqube/sonarqube-25.4.0.105899/bin/macosx-universal-64/sonar.sh start
  • http://localhost:9000にアクセス
    • デフォルトのユーザー名とパスワードはadmin/admin

SonarScannerのインストール

Mavenを使用する場合
  • https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/scanners/sonarscanner-for-maven/
  • https://central.sonatype.com/artifact/org.sonarsource.scanner.maven/sonar-maven-plugin/overview
  • pom.xmlのpluginタグ内に以下のコードを追加
    <groupId>org.sonarsource.scanner.maven</groupId>
    <artifactId>sonar-maven-plugin</artifactId>
    <version>5.1.0.4751</version>
    
  • http://localhost:9000/projects/createにアクセス
  • Create a local projectをクリック
  • Project display name、Project key、Main branch nameを入力
  • http://localhost:9000/account/securityにアクセス
  • Generate TokenセクションのName、Type、Expires inを入力 
  • pom.xmlのpropertiesタグ内に以下のコードを追加
    <sonar.projectKey><プロジェクト名></sonar.projectKey>
    <sonar.host.url>http://localhost:9000</sonar.host.url>
    <sonar.token>${SONAR_TOKEN}</sonar.token>
    
  • コンパイラ言語を解析する場合
    • Qualitas CorpusにあるSystems/<システム名>/<システムのバージョン>/srcディレクトリをソースディレクトリとして、Systems/<システム名>/<システムのバージョン>/binディレクトリとバイナリディレクトリとして指定
      • 例: mvn sonar:sonar -DSONAR_TOKEN=<SonarQubeのトークン> -Dsonar.sources=Systems/ant/ant-1.8.4/src -Dsonar.java.binaries=Systems/ant/ant-1.8.4/bin -Dsonar.scm.disabled=trueを実行
  • -Dsonar.verbose=true -Xオプションを追記することで、デバッグに役立つ詳細なログを確認できる
  • http://localhost:9000/projectsにアクセスすると解析結果を確認できる
  • SonarQubeの場合はant1.1などの古いシステムも解析できる

得られた成果

  • リファクタリングの具体的な手順を理解できた
  • リファクタリングを開発プロセスに導入する方法を理解できた
  • CheckstyleとSonarQubeの実行環境を作成できた

直面した課題

  • Checkstyleは古いシステムで使用されているJavaの構文を解析できず、途中で処理が中断してしまう
    • Checkstyleの動作の一貫性を保ったまま、この問題に対処する方法は今のところない
  • SonarQubeは不適切な文字が挿入されているソースファイルを解析できず、途中で処理が中断してしまう
    • ソースファイルに含まれる不適切な文字を事前に削除しておく必要がある
  • SonarQubeはルールセットが多く、かつソースファイルとバイナリファイルの両方を解析するため、1つのシステムの解析が完了するまでに2分ほどかかる

来週の計画

  • SonarQubeのJavaルールセットのうち、保守性に関するルールを整理
  • CheckstyleとSonarQubeが行う処理の概要をソースコードを読んで理解
  • SonarQubeのルールセットのうち、異常検出アルゴリズムと組み合わせて使用できるルールを整理
  • Qualitas Corpusで取り上げられているシステムをカテゴリーごとに分類