Strict Exception Rules
이 룰셋은 오류 처리에 관한 엄격한 가이드라인을 제공한다.
AvoidCatchingThrowable
Throwable을 catch절에서 처리하지 말자. java.lang.Throwable은 모든 오류 및 예외에 대한 수펴클래스이며, 이 객체로 오류 처리를 하면 명확한 오류 처리를 수행할 수 없다.
public class Foo { public void bar() { try { ... //throwable로 오류 처리를 하지말자. //너무 범위가 넓어 명확하지 않은 오류 처리이다. } catch (Throwable th) { th.printStackTrace(); } } }
SignatureDeclareThrowsException
오류 처리를 위하여 Exception을 반환하는 것은 좋지 않은 방법이다. 이는 문서 처리 및 모호한 인터페이스를 이해하기 어렵다. 해결방법으로는 RuntimeException을 바탕으로 만들어진 클래스를 사용하던가, 확인된 오류로 처리하자.
//단순히 Exception을 사용하지 말고 더욱 명확한 오류 객체를 사용하자. public void methodThrowingException() throws Exception { }
ExceptionAsFlowControl
Exception을 오류처리의 GOTO같은 흐름 관리를 위해서 사용하지 말자. 디버깅 할때 힘들다.
public class Foo { void bar() { try { try { ... } catch (Exception e) { throw new WrapperException(e); // 위와 같은 처리는 GOTO를 사용해서 처리하는 것과 별 차이가 없다. // 위와 같은 처리는 Exception에서 다시 WrapperException 처리로 이동하는 이중 처리이다. } } catch (WrapperException e) { // 뭔가 오류 처리 } } //이런 식으로 각각 처리하자. void bar() { try { ... } catch(WrapperException e) { ... } catch(Exception e) { ... } } //JDK 7에서는 다음과 같이도 가능하다. void bar() { try { ... } catch(WrapperException e | Exception e) { ... } } }
AvoidCatchingNPE
일반적인 환경에서 절대 NPE(NullPointerException)을 단순히 catch절로 잡아서 처리하지 말자. 대부분의 NPE가 발생할 때 NPE는 표면적인 이유고 그 아래 근본적인 오류의 원인이 숨어있는 경우가 있다.
public class Foo { void bar() { try { // do something } catch (NullPointerException npe) { //NPE는 더욱 근본적인 오류의 원인이 숨겨지는 경우가 있다. //그러므로, NPE를 단순히 catch절로 숨기지 말자. } } }
AvoidThrowingRawExceptionTypes
단순히 RuntimeException, Throwable, Exception 또는 Error를 전달하지말고 더욱 명확한 오류 타입들로 전달하자.
public class Foo { public void bar() throws Exception { //이런식의 오류처리는 명확한 오류를 인지하기 힘들다. throw new Exception(); } }
AvoidThrowingNullPointerException
오류를 NPE(NullPointerException)를 발생시켜 전달할 경우, 개발자는 이 오류가 VM(virtual machine)에서 전달한 것으로 인지할 수 있다. 그러므로, IllegalArgumentException을 NPE 대신 사용해서, 더욱 명확하게 프로그래머가 설정한 오류로 인식하게 하자.
public class Foo { void bar() { throw new NullPointerException(); //위의 NPE가 아닌 아래의 방식으로 쓰자. throw new IllegalArgumentException(); } }
AvoidRethrowingException
catch절에서 오류를 재전달하는 것은 단지 코드 길이를 늘리고 runtime 복잡성을 높일 뿐이다.
public class Foo { void bar() { try { ... } catch (SomeException se) { //오류를 재전달하는 것은 아무런 의미가 없다. throw se; } } }
DoNotExtendJavaLangError
Error 객체는 시스템 오류(system exception) 객체이다 . 절대 상속받아서 사용하지말자.
//시스템 오류 객체를 상속하여 사용할 이유는 없다. public class Foo extends Error { }
DoNotThrowExceptionInFinally
finally절에서 exception을 발생시켜 전달하는 것은 매우 혼란스럽다. 이런 방식은 또 다른 오류 또는 코드상의 결함을 만들어 낸다. 이런 부분은 깔끔하게 삭제하자. 참고: 이 룰은 Lint4j의 "A throw in a finally block"의 룰을 PMD로 구현한 것이다.
public class Foo { public void bar() { try { ... } catch( Exception e) { //오류 처리 } finally { // 이게 과연 좋은 생각인지 고민해보자. throw new Exception(); } } }
AvoidThrowingNewInstanceOfSameException
catch절 내에서 같은 오류 객체의 새로운 인스턴스를 만들어 재전달 하는 것은 단지 코드의 길이를 늘리고 runtime 복잡도를 올릴 뿐이다.
public class Foo { void bar() { try { ... } catch (SomeException se) { // 무의미한 코드 throw new SomeException(se); } } }
AvoidCatchingGenericException
NullPointerException, RuntimeException, Exception 같은 generic exception을 catch절에서 처리하는 것은 피해야한다.
package com.igate.primitive; public class PrimitiveType { public void downCastPrimitiveType() { try { System.out.println(" i [" + i + "]"); //밑의 모든 오류 처리는 그리 좋은 방법이 아니다. } catch(Exception e) { e.printStackTrace(); } catch(RuntimeException e) { e.printStackTrace(); } catch(NullPointerException e) { e.printStackTrace(); } } }
AvoidLosingExceptionInformation
Catch절에서 아무런 정보를 사용하지 않고 오류 객체의 접근자를 호출하는 것은 코드 길이만 늘리는 일이다. 이런 호출을 삭제하거나, 결과를 반환하자.
public class Foo { void bar() { try { // do something } catch (SomeException se) { //아무런 의미가 없는 코드 se.getMessage(); } } }
해당 URL: http://pmd.sourceforge.net/pmd-4.2.6/rules/strictexception.html