maven PMD plugin 사용해서 문제되는 코드 검출하기
개요
PMD 는 정적 소스 코드 분석기로 사용하지 않는 변수나 아무 일도 하지 않는 catch 구문등 문제가 될 만한 부분을 찾아준다.
이제는 Java 코드뿐만 아니라 Java Script 나 PLSQL 도 지원하며 추가로 복사 & 붙여넣기 검출기인 CPD 를 포함하고 있어서 중복 코드를 검출할 수도 있다.
maven 설정
pmd 는 site phase 에서 실행하는 것을 개인적으로 선호하므로 <reporting> 부분에 추가한다.
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> </properties> <reporting> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-pmd-plugin</artifactId> <version>3.2</version> <configuration> <linkXref>true</linkXref> <rulesets> <ruleset>file:///${project.basedir}/my-pmd-ruleset.xml</ruleset> </rulesets> </configuration> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>cobertura-maven-plugin</artifactId> <version>2.6</version> </plugin> </plugins> </reporting>
- 2 line
프로젝트 소스의 encoding을 지정하며 pmd는 여기에 지정한 encoding 을 사용하게 되며 설정하지 않았을 경우 UTF-8 을 사용한다. pmd 에만 별도로 지정하려면 <configuration> 항목에 <sourceEncoding> 으로 설정하면 된다. - 3 line
보고서의 출력 인코딩을 지정한다. - 14 line
사용할 커스텀 룰셋의 위치를 설정하며 URL 형식으로 지정하지 않으면 클래스 패스에서 찾게 된다. 커스텀 룰셋을 사용하는 가장 좋은 방법은 메이븐 프로젝트에 룰셋을 넣어두고 file:/// 형식 URL 로 지정하는 것이다. 절대 경로를 사용해야 하므로 maven의 ${project.basedir} 프로퍼티를 활용하자.
Custom rule set
사용하지 않는 변수에 대해서 검사하는 룰인 UnusedLocalVariable 와 UnusedPrivateField 를 포함하면 PMD 보고서 양이 너무 많아져서 개발자가 지레 겁 먹는 경우가 많아지므로 일정 수준 이상의 품질 목표를 달성한 후에 필요에 따라 추가하자.
Design
AvoidReassigningParameters
SwitchDensity
ConstructorCallsOverridableMethod
AvoidThrowingRawExceptionTypes
logging 룰셋
AvoidPrintStackTrace
<rule ref="rulesets/java/logging-java.xml/AvoidPrintStackTrace"/>
위 룰셋을 적용하면 운영에 올라가면 예외를 먹어버려서 머리에 쥐가 나게 만드는 아래와 같은 코드를 사전에 검출할 수 있다.
class Foo { void bar() { try { // do something } catch (Exception e) { e.printStackTrace(); } } }
SystemPrintln
<rule ref="rulesets/java/logging-java.xml/SystemPrintln"/>
Logger 대신 System.out.print* 나 System.err.print* 로 프린트하는 코드를 검출할 수 있다.
Basic 룰셋
EmptyCatchBlock
<rule ref="rulesets/java/basic.xml/EmptyCatchBlock"/>
catch 구문에서 예외처리를 아무것도 안 하는 문제 많은 코드를 검출할 수 있다.
public void doSomething() { try { FileInputStream fis = new FileInputStream("/tmp/bugger"); } catch (IOException ioe) { } }
EmptyIfStmt
<rule ref="rulesets/java/basic.xml/EmptyIfStmt/">
if 문에서 아무 짓도 안 하는 코드를 검출한다.
public class Foo { void bar(int x) { if (x == 0) { // empty! } } }
PMD Priority
PMD 의 룰에 우선순위를 지정할 수 있다. 다음은 catch 구문에 처리 로직이 없을 경우 우선 순위 1로 보고하는 예제이다.
<rule ref="rulesets/java/basic.xml/EmptyCatchBlock" message="Must handle exceptions"> <priority>1</priority> </rule>
PMD 의 의 우선순위는 총 5가지가 정의되어 있다.
- Change absolutely required. Behavior is critically broken/buggy.
- Change highly recommended. Behavior is quite likely to be broken/buggy.
- Change recommended. Behavior is confusing, perhaps buggy, and/or against standards/best practices.
- Change optional. Behavior is not likely to be buggy, but more just flies in the face of standards/style/good taste.
- Change highly optional. Nice to have, such as a consistent naming policy for package/class/fields...
Ref
- PMD Rulesets index: Current Rulesets
- How to make a new rule set
- Rule guidelines
- How to make a new rule set - http://pmd.sourceforge.net/pmd-5.1.3/howtomakearuleset.html