Ace-T's Blog 내 검색 [네이버 커넥트 이웃 합니다~^-^/ 요청 大 환영~~]

자바 예외처리를 생각해보자.

Language/Java 2016.09.26 18:16
[Good Comment!!, Good Discussion!!, Good Contens!!]
[ If you think that is useful, please click the finger on the bottom~^-^good~ ]
by ace-T


예외의 종류는 2가지로 보면 된다.

checked exception과 unchecked exception

말그대로 체크가 되는 예외와 예기치 못하게 발생하는 예외를 뜻한다. 

또한 unchecked exception은 runtime exception 이라고 많이 불리운다.

여기서 생각해보아야 할 것이 있다. 어떤 처리를 해주어야 예외처리를 잘하는 걸까?

보통은 Exception가 발생하면 잡아서 에러로그를 찍어주거나 상위로 올려주어서 처리를 하기도 한다.

try {

   ... 블라블라 ...

} catch(Excetpion e) {

   logger.error(e.getMessage);

}

토비책에서도 제대로된 예외처리를 하라고 살짝 나오기도 한다. 

과연..어떤 예외처리가 제대로된 예외처리일까? 사람마다 다를수 있을것 같기도 하다.(책임과 구조가 중요하기 때문..)

다음 RND 스터디(지인들과 만든 스터디 그룹)에서 토론해보면 좋을것 같다. 

개인적으로는 

1) 런타임 예외에 대한 것을 아래처럼 공통화(소스)를 한다!

예)

public class CommonLineupException extends RuntimeException{

    public static final Logger logger = LoggerFactory.getLogger(CommonLineupException.class);

    public CommonLineupException(String message){

        super(message);

        logger.error(message);

    }

}

2) 런타임 예외는 발생 시킨다! 고려사항으로 런타임 예외가 났을 경우 어떻게 처리를 해주는가를 더 생각해봐야한다.

  - MVC 구조라면 컨트롤러까지 올려서 관련 내용 처리 하기
  - api라고 한다면 유용정보(에러로그) 남기기


3) 또한 service -> service 구조이거나 service안에 여러 메소드들로 만들어져있다면

런타임 예외가 발생하는 메소드들이 그책임을 다해야 한다. 그안에서 에러로그와 런타임 예외를 발생 시켜 위로 올려주거나 하면 된다.


팁 : 스프링프레임워크에서는 예외를 잘할 수 있도록 도움을 주는 어노테이션이 존재한다.

참고 : https://www.mkyong.com/spring-mvc/spring-mvc-exceptionhandler-example/ 

또한 db단하고 붙어있다면 롤백 유무와도 상관이 있다. 롤백이 되려면 런타임 예외에만 가능하기 때문이다.


정리하자면..런타임 예외를 잘이용하고 에러로그를 쉽게 오류를 찾을 수 있도록 정보를 넣을수 있도록 한다.


   - 끝 - 

acet 박태하가 추천하는 readtrend 추천글!

설정

트랙백

댓글

:::: facebook을 이용하시는 분들은 로그인 후 아래에 코멘트를 남겨주세요 ::::

이펙티브 자바) 규칙 59, 60, 61, 62, 63, 64, 65

Language/Java 2015.07.30 01:44
[Good Comment!!, Good Discussion!!, Good Contens!!]
[ If you think that is useful, please click the finger on the bottom~^-^good~ ]
by ace-T

규칙 59. Avoid unnecessary use of checked exceptions


 checked exceptions

 Exception

 can recover

 IOException, 

IllegalArgumentExceptions

 uncheked exceptions

 RuntimeException

 can not recover

 transaction

NullPointerException


핵심요약 : checked exceptions 은 너무 남발하면 프로그램을 복잡하게 만든다.

그러므로 훌륭한 프로그래머가 되기위해서는 생각해보아야 한다. 무엇을?

1) 예외적인 상황을 막을수 있는가?   2) 예외 상황에 대한 조치를 취할 수 있는가?

막을수 없고, 조치를 취할 수 없다면(can't recover) runtimeException을 고려!

unchecked exception을 사용!(아래의 예제 참고~)

   // Invocation with checked exception

   try {

       obj.action(args);

   } catch(TheCheckedException e) {

       // Handle exceptional condition

       ...

   }

 

// Invocation with state-testing method and unchecked exception

   if (obj.actionPermitted(args)) {

       obj.action(args);

   } else {

       // Handle exceptional condition

       ...

   }



규칙 60Favor the use of standard exceptions

 어떤 예외를 재사용할 지 용도에 맞게 결정하여 사용하도록 하자!

  (단, 기존 예외의 하위 클래스를 자유로이 만들어 사용해도 좋다(규칙 63)


규칙 61Throw exceptions appropriate to the abstraction

     메서드가 하는 일고 뚜렷한 관련성이 없는 예외가 발생하면 당혹스럽다.

     해결방안

상위계층에서는 하위 계층에서 발생하는 예외를 반드시 받아서 상위계층 추상화 수준에 맞는 예외로 바꿔서 던져야 함.

이것을 exception translation 이라고 부른다.

예제1)


  // Exception Translation 

  try {

       // Use lower-level abstraction to do our bidding

       ...

   } catch(LowerLevelException e) {

       throw new HigherLevelException(...);

 }  


예제2) List<E> interface의 명세를 보면 예외변환이 필요함을 알수 있다.


public interface List<E> extends Collection<E>
/**
* Returns the element at the specified position in this list.
*
* @param index index of the element to return
* @return the element at the specified position in this list
* @throws IndexOutOfBoundsException if the index is out of range
* (<tt>index &lt; 0 || index &gt;= size()</tt>)
*/
E get(int index);


/**

* Returns the element at the specified position in this list. * 

@throws IndexOutOfBoundsException if the index is out of range * 

({@code index < 0 || index >= size()}).

*/

   public E get(int index) {

       ListIterator<E> i = listIterator(index);

       try {

           return i.next();

       } catch(NoSuchElementException e) {

           throw new IndexOutOfBoundsException("Index: " + index);  // exception translation 

       }

} 


예외 연결(exception chaining)

하위 계층의 예외를 상위 계층의 생성자에게 전달한다. 

Throwable.getCause를 호출하면 해당 정보를 꺼낼수 있으며 디버깅에 용이하다!


   // Exception with chaining-aware constructor

   class HigherLevelException extends Exception {

       HigherLevelException(Throwable cause) {

           super(cause);

       }

  }  


Throwable 

 initCause() to set cause, and getCause() to access cause.


규칙 62Document all exceptions thrown by each method

  • checked exceptions은 메서드의 throws 절에 나열
  • uncheked exceptions은 throws절에는 적지마라.

     프로그래머는 문서만 보면 무엇이 checked exception인지 무엇이 unchecked exception인지 알수 있다.


규칙 63Include failure-capture information in detail messages

    오류 정보를 알아내기 위해서는 오류의 상세메시지에 "예외에 관계된" 모든 인자와 필드의 값을 포함 시켜야 한다.

    간단히 말해 예외에서 나는 오류정보는 프로그래머 등의 사람들이 보게 되며, 이것은 오류를 쉽게 파악하거나 

    해결할 수 있게 해주는 메시지이다.


규칙 64. Strive for failure atomicity

    예외를 던지고 난 뒤에도 객체의 상태가 사용 가능한 상태로 남아 있으면 좋다.

    다시 말하면 메서드 호출이 정상적으로 처리되지 못한 객체의 상태는 메서드 호출 전 상태와 동일해야 한다.

    이것을 만족했을 때 이 메서드는 실패 원자성(failure atomicity)을 갖추었다고 한다.


실패 원자성을 달성하는 방법

  1. 가장 간단한 방법은 변경 불가능한 객체로 설계하는 것이다.(규칙 15) 또한, 변경 가능한 객체의 경우는 연산을 하기 전에 인자 유효성(validity)을 체크하는 것이 가장 보편적인 방법이다.(규칙 38) 
  2. computation so that any part that may fail takes place before any part that modifies the object / Compute the result first, to see whether there is an exception. If result is valid, then set it to the object.
  3. 연산 수행 도중에 발생하는 오류를 가로채는 복구 코드(recovery code)를 작성한다.
  4. 객체의 임시 복사본상에서 필요한 연산을 수행하고, 연산이 끝난 다음에 임시 복사본의 내용으로 객체 상태를 바꾸는 방법.


규칙 65.  Don’t ignore exceptions

    빈 catch 블록은 사용하지 말고, 최소한 예외를 무시해도 괜찮은 이유라도 주석으로 남겨둬라!


  // Empty catch block ignores exception - Highly suspect!

   try { ...

   } catch (SomeException e) {

   } 


-  END -






acet 박태하가 추천하는 readtrend 추천글!

설정

트랙백

댓글

:::: facebook을 이용하시는 분들은 로그인 후 아래에 코멘트를 남겨주세요 ::::

티스토리 툴바