Java ‐ 가능한 한 실패 원자적으로 만들라[Effective Java Item 76] - thought-corner/Backend-PlayGround GitHub Wiki
실패 원자적 (failure-atomic)인 메서드
- 실패 원자적인 메서드란, 호출된 메서드가 실패하더라도 해당 객체는 메서드 호출 전 상태를 유지해야 하는 메서드를 말한다.
실패 원자적인 메서드를 어떻게 만들까?
1. 불변 객체로 만들기
- 불변 객체는 태생적으로 실패 원자적이다.
- 메서드가 실패하면 새로운 객체가 만들어지지는 않을 수 있으나 기존 객체가 불완전한 상태에 빠지는 일은 결코 없게 된다. 불변 객체의 상태는 생성 시점에 고정되어 절대 변하지 않기 때문이다.
2. 가변 객체의 메서드인 경우 작업 수행 전 매개변수의 유효성을 검사하기
- 객체의 내부 상태를 변경하기 전에 잠재적 예외 가능성 대부분을 걸러낼 수 있는 방법이다.
public Object pop() {
if (size == 0)
throw new EmptyStackException();
Object result = elements[--size];
elements[size] = null; // 다 쓴 참조 해제
return result;
}
3. 객체의 임시 복사본에서 작업을 수행한 다음, 작업이 성공적으로 완료되면 원래 객체와 교체하는 것
- 데이터를 임시 자료구조에 저장해 작업하는게 더 빠를 때 적용하기 좋은 방식
- 어떤 정렬 메서드에서 정렬을 수행하기 전에 입력 리스트의 원소들을 배열로 옮겨 담는다. 배열을 사용하면 정렬 알고리즘의 반복문에서 원소들에 훨씬 빠르게 접근할 수 있다.
- 정렬에 실패하더라도 입력 리스트는 변하지 않는 효과를 덤으로 얻게 된다.
4. 작업 도중 발생하는 실패를 가로채는 복구 코드를 작성하여 작업 전 상태로 되돌리는 방법
- 내구성을 보장해야 하는 자료구조에 쓰이는데 자주 쓰이는 방법은 아니다.
실패 원자성은 항상 달성할 수 있는가?
- 실패 원자성은 일반적으로 권장되는 덕목이지만 항상 달성할 수 있는 것은 아니다.
Error는 복구할 수 없으므로AssertionError에 대해서는 실패 원자적으로 만들려는 시도조차 할 필요가 없다.
그럼 실패 원자성을 항상 보장해야 할까?
- 실패 원자적으로 만들 수 있더라도 항상 그리 해야 하는 것은 아니다. 실패 원자성을 달성하기 위한 비용이나 복잡도가 아주 큰 연산도 있기 때문이다.
- 메서드 명세에 기술한 예외라면 설령 예외가 발생하더라도 객체의 상태는 메서드 호출 전과 똑같이 유지되어야 하는 것이 기본 규칙이다. 이 규칙을 지키지 못한다면 실패 시의 객체 상태를 API 설명에 명시해야 한다.