🤓 스터디/이펙티브 자바

[아이템 76] 가능한 한 실패 원자적으로 만들라

강켄트 2023. 4. 27. 19:39

 

메서드가 실패하더라도 해당 객체는 메서드 호출 전 상태(정상적으로 사용할 수 있는 상태)를 유지해야 한다.

이러한 특성을 실패 원자적(failure-atomic)이라고 한다.

 

실패 원자적으로 만드는 방법

✅ 메서드를 불변 객체로 설계하기 

메서드가 실패하면 새로운 객체가 만들어지지 않고,

기존 객체가 불안정한 상태에 빠지는 일도 결코 없다.

불변 객체의 상태는 생성 시점에 고정되어 절대 변하지 않기 때문이다.

 

가변 객체의 메서드의 작업 수행 전에 매개변수의 유효성을 검사하기 

객체의 내부 상태를 변경하기 전에 잠재적 예외의 가능성 대부분을 걸러낼 수 있다.

 

객체의 임시 복사본에서 작업을 수행한 다음, 작업 성공 후 원래 객체와 교환하기

데이터를 임시 자료구조에 저장해 작업하는 게 더 빠를 때 적용하기 좋은 방식이다.

ex)

어떤 정렬 메서드에서 정렬을 수행하기 전에 입력 리스트의 원소들을 배열로 옮겨 담는다.

배열을 사용하면 정렬 알고리즘의 반복문에서 원소들에 훨씬 빠르게 접근할 수 있기 때문

(정렬에 실패하더라도 입력 리스트는 변하지 않는다.)

 

작업 도중 발생하는 실패를 가로채는 복구 코드를 작성해 작업 전 상태로 되돌리기

주로 디스크 기반의 내구성을 보장해야 하는 자료구조에 쓰인다.(자주 쓰이는 방법은 아니다.)

 

 

실패 원자성은 권장되는 덕목이지만 항상 달성할 수 있는 것은 아니다.

ex)

두 스레드가 동기화 없이 같은 객체를 동시에 수정한다면 그 객체의 일관성이 깨질 수 있다.

ConcurrentModificationException을 잡아냈다고 해서 그 객체가 여전히 쓸 수 있는 상태라고 가정할 수 없다.

💡ConcurrentModificationException : 보통 리스트나 Map 등, Iterable 객체를 순회하면서 요소를 삭제하거나 변경을 할 때 발생

 

또한 Error는 복구할 수 없기 때문에 AssertionError에 대해 실패 원자적으로 만들 필요가 없다.

 

 

정리

메서드 명세에 기술한 예외라면 예외 발생 시 객체의 상태는 메서드 호출 전과 똑같이 유지돼야 한다는 것이 기본 규칙!그렇지 못하다면 실패 시 객체 상태를 API 설명에 명시하자!