JDepend + Eclipse + Maven2

JDepend는 Java패키지간의 의존성에 대한 수치들을 알려 주는 도구입니다.

JDepend의 Eclipse의 Plugin은 http://andrei.gmxhome.de/eclipse/를 Update site에 추가하면 설치할 수 있습니다. 다음의 링크들에서 보다 자세한 내용을 참조할 수 있습니다. 분석을 하고자 하는 소스폴더 위에서 우클릭을 한 후 'Run JDepend Analysis' 메뉴를 선택하면 의존성 분석 결과가 나옵니다.

eclipse-jdepend.jpg

이를 Maven을 통해서 생성하는 jdepend-maven-plugin 은 pom.xml에 아래와 같이 추가할 수 있습니다.

<reporting>

.....

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>jdepend-maven-plugin</artifactId>
  <version>2.0-beta-2</version>
</plugin>

</reporting>

mvn jdepend:generate 또는 mvn site 명령을 통해서 보고서가 생성됩니다. mvn site로 실행했다면 Hudson의 프로젝트 홈에서 Maven Generated Site 메뉴를 통해서도 확인할 수 있습니다. 샘플페이지 에 생성된 보고서의 형식이 나와있습니다.

jdepend-report.jpg

JDepend 첫페이지나 생성된 보고서 안에서도 위의 요약 테이블에 수치들에 대한 설명이 잘 나와있습니다. 간단히 요약해서 정리하면,

  • TC (Total Classes) : 전체 클래스 수. CC + AC

  • CC (Concrete Classes) : Inteface나 추상클래스가 아닌 구상 클래스 수

  • AC (Abstract Classes) : Interface나 Abstract Class로 선언된 클래스 수

  • Ca (Afferent Couplings) : 이 패키지를 의존하고 있는 다른 패키지의 수. 이 패키지의 책임감을 나타내는 지표

  • Ce (Efferent Couplings) : 이 패키지가 의존하고 있는 클래스가 있는 다른 패키지의 수. 이 패키지의 독립성을 나타내는 지표.

  • A (Abstractness) : 총 클래스 갯수 중 인터페이스나 추상클래스의 비율. 1이라면 해당 패키지는 추상클래스나 인터페이스 밖에 없는 것.

  • I (Instability) : 총 결합도 중 이 패키지의 외부의존성의 비율 (Ce / (Ce + Ca)). 변화에 대한 내성을 나타내는 지표. I=0이라면 완전하게 안정적인 것.

  • D (Distance from Main Sequence) : 이상적인 균형의 상태인 A + I = 1 의 함수에서 수직으로 떨어진 거리. (아래 그래프 참조)

onjava/2004/01/21/graphics/figure3.gif

가장 중요한 것은 패키지 간의 순환참조를 보여주는 Cycles 부분입니다.

jdepend-cycles.jpg

순환참조 관계의 패키지들은 부분적으로 배포될 수도 없고, 한 패키지를 변경할 때 그 영향력을 파악하기도 힘들게 만듭니다. 순환 참조에 대한 자세한 내용은 아래의 링크를 참조하시기 바랍니다.

JavaNCSS + Maven2 + Hudson

JavaNCSS를 Maven2을 통해 실행하고, Hudson을 통해 리포트를 확인하는 과정을 정리했습니다. JavaNCSS는 주석이 아닌 라인수(Non Commenting Source Statements,NCSS)와 순환복잡도 수 (Cyclomatic Comlexity Number, CCN) 등을 측정해 주는 도구입니다.

JavanNCSS에 관한 eclipse 플러그인도 찾을 수는 있었지만(http://sourceforge.net/projects/jncss4eclipse/ ) 가장 최신버전이 2002년에 올라온 것이라서 적용하지 않기로 했습니다.

그리고, JavaNCSS에 대한 Maven의 플러그인도 javancss-maven-pluginmaven-javancss-plugin의 2가지가 존재했는데, javancss-maven-plugin 쪽이 보다 문서화가 잘 되어 있어서 그 쪽을 선택했습니다.

pom.xml 에 아래 선언을 추가합니다.

<reporting>

...

   <plugin>

     <groupId>org.codehaus.mojo</groupId>
     <artifactId>javancss-maven-plugin</artifactId>
     <version>2.0-beta-2</version>
      <configuration>
      <forceEncoding>utf-8</forceEncoding>
       </configuration>
    </plugin>
  </plugins>
</reporting>

그리고는 mvn javancss:report javancss:check 로 플러그인을 실행시켜 봅니다. 각각의 골에 대한 설명은 아래 페이지에서 보시면 됩니다.

제외하거나 추가할 파일을 지정하려면 아래의 configuration 태그 아래에 includes, excludes 태그로 지정하면 됩니다.

<configuration>

.....
  <includes>
    <include>**/*foo.java</include>
  </includes>
  <excludes>
    <exclude>**/bar.java</exclude>
  <exclude>**/foobar.java</exclude>
  </excludes>
</configuration>

CCN이나 NCSS값의 한계 허용치는 아래와 같이 지정합니다.

<configuration>
....
  <failOnViolation>true</failOnViolation>
  <ccnLimit>12</ccnLimit>
  <ncssLimit>90</ncssLimit>
</configuration>

한가지 주의할 점은, 2.0-beta-2 버전을 실행할 경우, 메서드 내부에 annotation선언이 있다면 아래와 같은 에러메시지를 받게 됩니다.

Encountered "@ SuppressWarnings ( \"unused\" ) int notUsedVariable =" at line xxx, column yyy.

이 것은 javancss-maven-plugin 버전 2.0-beta-2가 이 의존하고 있는 JavaNCSS 버전 29.49 에서 가지고 있는 버그입니다. (http://jira.codehaus.org/browse/MJNCSS-16 참조) JavaNCSS 버전 29.50에서는 해결된 문제이고, 이 플러그인의 최신 버전인 javancss-maven-plugin 2.0-beta-3버전에서는 이런 문제가 발생하지 않는다고 합니다. 그런데, codehause의 Maven Repository를 뒤져보니 (http://repository.codehaus.org/org/codehaus/mojo/javancss-maven-plugin/) 아직 2.0-beta-3버전은 올라와 있지 않습니다. snapshop 버전을 찾아서 쓸 수도 있겠지만, 그것보다는plugin 설정에서 dependency설정을 덥어쓰는 편이 더 간편하게 느껴졌습니다. pom.xml 의 build절에 아래와같이 추가하면 됩니다.

<build>

   <plugin>
     <groupId>org.codehaus.mojo</groupId>
        <artifactId>javancss-maven-plugin</artifactId>
        <version>2.0-beta-2</version>
        <dependencies>
          <dependency>
            <groupId>javancss</groupId>
              <artifactId>javancss</artifactId>
              <version>29.50</version>
             </dependency>
         </dependencies>
     </plugin>
     </plugins>
  </build>

생성된 리포트를 보기 위해서, Hudson에서는 프로젝트에서 Configure 설정에서 Publish Java NCSS report를 선택을 합니다.

hudson-javancss-config.jpg

그리고는 javancss:report Goal이 포함된 빌드를 실행시켰다면 프로젝트 홈 화면에서 Java NCSS Report라는 링크가 생기게 됩니다.

hudson-javancss-menu.jpg

클릭을 하면 생성된 리포트를 볼 수가 있죠. (패키지명은 제가 지웠습니다.)

hudson-javancss-report.jpg

Maven에서 mvn site명령으로 site 절(phrase)까지 들어갔다면 리포트를 모은 페이지를 따로 생성해 주기도합니다. Hudson의 프로젝트 메인화면에서 Maven-generated site 링크를 통해서 보실 수 있습니다.Hudson에서 생성해주는 페이지가 더 이쁘기는하지만, JavaNCSS의 보고서는 Maven-generated site가 더많은 정보를 제공합니다. 예를 들면 가장 주석을 제외한 라인수(NCSS)가 많은 30위까지의 클래스들, 메소드들 같은 순위등같은 것들을 확인할 수 있습니다.

mvn-site-reports.jpg

PMD + Eclipse + Maven2 + Hudson

코드 검사도구인 PMD 를 Eclipse plugin을 설정하고, Maven을 통해서도 같은 규칙으로 코드를 검사한 보고서를 생성하고, Hudson을 통해서 확인하는 과정을 정리해 봤습니다.

Eclipse에서는 update site를 http://pmd.sf.net/eclipse 로 지정해서 플러인을 설치합니다.

Eclipse 메뉴의 Window- Preferences를 가면 Rule설정 파일을 export, import할 수 있는 기능이 있습니다.

eclipse-pmd-rule.jpg

Project의 Properties에도 PMD관련 설정이 있습니다. 외부에서 만든 Rule파일을 바로 참조해도 되고, 여기서 설정된 것을파일로 생성할 수도 있습니다. 이미 있는 프로젝트에서 Rule를 설정할 때는 Project의 Properties에서 Rule들을고른 후에 생기는 warning이나 error를 보고 warning이 안 뜨게 소스를 고거나 Rule을 제외한 후, 최종결정Rule들로 Ruleset 정의 파일을 생성하는 것이 편리할 것입니다. 저는 처음에 모든 Rule을 다 선택한 다음에warning들을 없애가면서 Rule들을 하나하나 검토해 나갔었습니다.

eclipse-pmd-project.jpg

위의 화면에서 Enable PMD를 선택하면 .project파일에 아래와 같은 부분이 추가될 것입니다.

<natures>
      ....
   <nature>net.sourceforge.pmd.eclipse.plugin.pmdNature</nature>
</natures>

이제 해당 프로젝트는 Eclipse의 Problems View에서 PMD에서 보고하는 error, warning까지 모두 다 뜨게됩니다. 개발을 하면서 Rule 준수에 대한 빠른 피드백을 얻기 위해 되도록 이 기능을 사용하는 것이 좋습니다. 대신 이미Project에 warning이 많으면 새로운 warning들이 잘 눈에 띄지 않게 되므로, Project를 warning없이깨끗히 정리한 다음에 사용할 것을 권장해 드립니다.

모든 Rule을 다 적용하면 아마 굉장히 많은 warning과 때로는 에러까지도 나올 것입니다. 그런 것들을 다 검토해서 포함시킬지를 결정해야 합니다. http://pmd.sourceforge.net/rule-guidelines.html를 참조하셔서, 프로젝트 상황에 맞게 적용해야겠죠. 그중 몇가지 Rule에 대해서만 언급을 하고 넘어가겠습니다.

  • Basic Rules-EmptryInitializer: PMD 5.0에서 추가된 룰로 Maven의 PMD plugin버전 2.4에서는 PMD 버전 4.2.2를 참조하기 때문에 이Rule은 지원되지 않습니다. 따라서 PMD의 Eclipse plugin에서 이를 지원한다고 할지라도 Maven plugin과같이 쓰기 위해서는 이 Rule을 반드시 제외해야 합니다.

  • Optimization Rules-LocalVariableCouldBeFinal과 Controversial Rules-AvoidFinalLocalVariable : 서로 상반되는 Rule로 한쪽 Rule을피하면 다른 쪽에 걸려드는 Rule입니다. 그래서 warning을 안보려면 둘 중에 하나는 꼭 제외해야 합니다. 그런데,final을 Local variable에 일일히 선언하는 것도 번거로운 일이고, 메소드 내의 inner class에서 참조해야되어서 꼭 final이 되어야하는 local variable도 있으므로, 둘 다 제외하는 것도 좋습니다

  • Controversial Rules-OnlyOneReturnRule : 메서드에서 return문이 여러 개일 경우 경고를 주는데, 메서드 중간의 return문은 복잡한 조건문의 구조를 단순하게 하는데 도움이 경우가 많고, 켄트벡의 구현패턴 7장 중 '보호절’을 보면 이를 권장하고 있습니다.

  • Design Rules-UnnecessaryLocalBeforeReturn: return 전에 따로 local 변수로 반환할 값을 선언할 때 주는 경고인데, 기능적으로는 별 의미 없는 코드이나,return 문장에는 @SupressWarning 의 Annotation을 추가할 수 없기 때문에, Annotation 적용범위를 최소화하기 위해 그런 선언이 필요한 때도 있습니다. (Java Language Spec 9.7, EffectiveJava 2nd Edition Item 24 참조)

검토해보니 가장 부담없이 적용가능한 RuleSet이 괄호에 대한 규칙을 정의하는 Braces Rules이고, Controversial Rules가 이름 그래도 가장 제외할 것이 많은 Rule Set입니다.

이런 과정을 거쳐서 선별된 Rule 정의 파일이 만들어지면 그것을 Maven의 PMD plugin에서도 참조할 수 있게 설정합니다. 저는 Rule설정 파일이름을 .ruleset으로 하고 pom.xml에 추가했습니다.

  <reporting>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-pmd-plugin</artifactId>
        <version>2.4</version>
        <configuration>
          <rulesets>
            <ruleset>$\{basedir}/.ruleset</ruleset>
          </rulesets>
          <sourceEncoding>utf-8</sourceEncoding>
          <targetJdk>1.6</targetJdk>
          <minimumTokens>10</minimumTokens>
        </configuration>
      </plugin>
  </reporting>

그리고는 mvn site 혹은 mvn pmd:pmd pmd:cpd 처럼 PMD plugin의 goal을 포함시킨 빌드를 한번 실행시켜 봅니다.

문제가 없이 돌아갔으면 hudson에도 PMD플러그인을 설정합니다.. PMD 플러그인의 goal이 포함된 빌드를 돌리고 나면PMD warning라는 링크가 해당 프로젝트에 생기고, 거기서 아래와 같은 보고서를 확인할 수 있습니다.

hudson-pmd-report.jpg