호출된 메서드가 실패해도 해당 객체는 메서드 호출 전 상태를 유지하는 특성을 실패 원자적이라고 한다. 우리는 메서드를 가능한 한 실패 원자적으로 만들어야 한다. 작업 도중 예외가 발생해도 그 객체를 정상적으로 사용할 수 있는 상태라면 호출자가 오류 상태를 복구할 수 있을 테니 더 유용하기 때문이다. 메서드를 실패 원자적으로 만드는 방법 1. 메서드를 불변 객체로 설계한다. 불변 객체는 태생이 실패 원자적이며 객체가 불안정한 상태에 빠지는 일은 생기지 않는다. 불변 객체는 생성 시점에 고정되어 변하지 않기 때문이다. 메서드가 실패하면 새로운 객체가 만들어지지 않을 뿐이다. 2. 매개변수의 유효성을 검사한다. 가변 객체를 다루는 메서드를 실패 원자적으로 만들기 위한 가장 쉬운 방법은 수행에 앞서 매개변수의 ..
김영한님의 자바 ORM 표준 JPA 프로그래밍 강의를 들으며 공부한 내용을 정리한 글입니다. 1. JPA란? JPA(Java Persistence API)는 자바 진영의 ORM 기술 표준이다. ORM(Object Realational Mapping)이란? 객체와 RDBMS 사이를 중간에서 매핑해주는 객체 관계 매핑 기술이다. JPA는 애플리케이션과 JDBC 사이에서 동작하며 Java의 객체와 RDBMS 사이를 매핑하는 역할을 한다. 프로그래머가 Entity를 작성하면 JPA는 이를 분석해서 자동으로 필요한 SQL을 생성한다. 따라서 프로그래머는 조금 더 객체 지향적인 관점에서 프로그래밍을 할 수 있게 된다. 2. JPA가 왜 필요할까? 기존의 SQL 중심의 개발에서는 객체에 필드를 추가하면 그와 관련된 ..
프로그램이 실패하면 자바는 그 예외의 스택 추적(stack trace) 정보를 자동으로 출력한다. 스택 추적 정보는 예외 객체의 toString 메서드를 호출해 얻은 문자열로, 보통은 클래스 이름 뒤에 상세 메시지가 붙는 형태이다. 예외의 toString() 메서드에 실패 원인에 관한 정보를 가능한 많이 담아 반환하는 것은 굉장히 중요하다. 실패 원인을 얻을 수 있는 유일한 정보일 수도 있고 재현하기 어려운 오류일 경우 더 자세한 정보를 얻기 어렵기 때문이다. 예외에 관여된 모든 매개변수, 필드의 값을 실패 메시지에 담자 예를 들어, IndexOutOfBoundsException의 상세 메시지에는 범위의 최솟값과 최댓값, 그리고 범위를 벗어난 인덱스의 값을 담아야 한다. 원인이 될 수 있는 모든 매개변수..
메서드가 던지는 예외는 그 메서드를 사용하는데 아주 중요한 정보다. 따라서 각 메서드가 던지는 예외를 문서화하는 것은 중요하며 충분한 시간을 쏟아야 한다. 검사 예외는 따로따로 선언하자 검사 예외는 항상 따로따로 선언하고, 각 예외가 발생하는 상황을 자바독의 @throws 태그를 활용해 정확히 문서화 하자. 공통 상위 클래스 하나로 통합해서 선언하는 일은 삼가야 한다. 극단적인 예로, Exception이나 Throwable을 던진다고 선언해서는 안 된다. 메서드 사용자에게 각 예외에 대처할 수 있는 힌트를 주지 못할뿐더러, 같은 맥락에서 발생할 수 있는 다른 예외들까지 모두 삼켜버려 API 사용성을 크게 떨어트린다. 잘못된 사용 방법 // 잘못 선언한 예 public void testMethod() th..
수행하려는 일과 관련 없는 예외가 나오면 당황스럽기 마련이다. 이는 메서드가 저수준 예외를 처리하지 않고 바깥으로 전파(throw)할 때 종종 일어나는 문제이다. 내부 구현 방식을 드러내어 윗 레벨 API를 오염시킬 수 있고, 구현 방식을 바꾸면 다른 예외가 튀어나와 기존 클라이언트 프로그램을 깨지게 할 수도 있다. 상위 계층에서 예외 번역을 하자 예외 번역이란 상위 계층에서 저수준 예외를 잡아 자신의 추상화 수준에 맞는 예외로 바꾸는 것을 말한다. 위에서 언급한 문제점을 피하기 위해서는 상위 계층에서의 예외 번역이 필요하다. try { ..// 저수준 추상화를 이용 } catch (LowerLevelException e) { // 추상화 수준에 맞게 번역 throw new HigherLevelExcep..
코드를 재사용하듯 예외도 재사용하는 것이 좋다. 자바 라이브러리는 대부분 API에서 충분한 수의 예외를 제공하고 있다. 그러니 가능한 표준 예외를 재사용하자. 표준 예외의 장점 1. 다른 사람이 익히고 사용하기 쉬워진다. 표준 예외를 사용하면 이미 많은 사람들에게 익숙해진 규약을 그대로 따르기 때문에 다른 사람들이 익히고 사용하기 쉬워진다. 2. 읽기 쉬워진다. 낯선 예외보다는 익숙한 예외를 사용하므로 읽기 쉬워지고 예외를 빠르게 파악할 수 있다. 3. 메모리 사용량과 클래스 적재 시간이 줄어든다. 표준 예외를 사용하면 예외 클래스를 별도로 만들지 않아도 된다. 따라서 메모리 사용량과 클래스 적재 시간이 줄어든다. 가장 많이 사용되는 표준 예외 NullPointerException null을 허용하지 않..
검사 예외를 잘 활용하면 프로그램의 안정성과 질을 높일 수 있다. 하지만 검사 예외를 과하게 사용하면 오히려 사용하기 불편한 API가 될 수 있다. 검사 예외와 비검사 예외 선택 기준 API를 제대로 사용해도 발생할 수 있는 예외 거나, 프로그래머가 의미 있는 조치를 취할 수 있는 경우라면 검사 예외를 그렇지 않다면 비검사 예외를 사용하자. 검사 예외 회피 방법 - 비검사 예외 아래의 코드는 API 사용자가 검사 예외를 처리하는 사례이다. // 비검사 예외를 호출한다. } catch (TheCheckedException e) { throw new AssertionError(); } // 에러 스택 코드를 출력하고 시스템을 종료한다. } catch (TheCheckedException e) { e.prin..
자바에서 문제 상황을 알리는 타입(throwable)으로는 검사 예외(checked Exception), 런타임 예외(Runtime Exception), 에러 이렇게 3가지를 제공한다. 언제 무엇을 사용해야 하는지 참고하면 좋은 지침들에 대해 알아보자. 검사 예외와 비검사 예외를 구분하는 기본 규칙 호출하는 쪽에서 복구하리라 예상되는 상황이라면 검사 예외를 사용하자. 검사 예외를 던지면 호출자가 그 예외를 catch로 처리하거나, 더 바깥으로 전파하도록 강제된다. 따라서 메서드 선언에 포함되는 예외는 해당 메서드를 호출했을 때 발생할 수 있는 유력한 결과를 나타낸다. 즉, API 설계자는 API 사용자에게 검사 예외(checked Exception)를 넘겨주어 그 상황에서 복구하라고 요구한 것이다. 따라..
예외는 예외 상황에서 쓸 의도로 설계되었다. 정상적인 제어 흐름에서 사용해서는 안되며, 이를 강요하는 API도 만들면 안 된다. 예외를 제어 흐름용으로 사용하지 말자 위 코드는 무한루프를 돌다가 배열의 끝에 도달해 ArrayIndexOutOfBoundsException이 발생하면 배열 순회를 끝낸다. 제어 흐름용으로 예외를 사용한 케이스이다. // 예외를 완전히 잘못 사용한 예 try { int i = 0; while(true) { range[i++].climb(); } } catch (ArrayIndexOutOfBoundsException e) { } 위 코드는 직관적이지 않아 무슨 일을 하는지 한눈에 알아보기 어렵다. 또한, 다른 문제점들도 존재한다. 예외를 제어 흐름용으로 사용하면 표준 관용구보다 ..