일반적으로 이야기해서, 메서드 호출이 정상적으로 처리되지 못한 객체의 상태는, 메서드 호출전 상태와 동일해야 한다. 이 속성을 만족하는 메서드는 실패원자성을 갖추었다고 한다.


 실패 원자성을 달성하는 방법은 여러가지다. 

  • 변경 불가능 객체로 설계하는 방법. 변경 불가능한 객체의 경우, 실패원자성은 덤이다. 메서드 호출이 실패하면 새로운 객체가 만들어지지 못할 수는 있게지만 기존 객체의 일관성이 깨지진 않는다. 변경 가능한 객체의 경우에는 실제 연산을 수행하기 전에 인자 유효성을 검사하는 것이 가장 보편적인 방법이다. 

물론 빈 스택에서 뭔가를 뽑아내려 하면, 굳이 첫 두줄이 없어도 예외가 나긴 하겠지만, 첫 두줄이 없으면 size필드의 일관성이 깨져서 음수로 바뀌게 된다. 그러니 이 메서드를 다시 호출하면 계속 문제가 생길 것이다.

  • 실패할 가능성이 있는 코드는 전부 객체 상태를 바꾸는 코드 앞에 배치하는 것.  계산을 실제로 수행해 보기 전에는 인자를 검사할 수 없을 때 이용 가능한 방법
  • 연산 수행 도중에 발생하는 오류를 가로채는 복구 코드를 작성하는 것. 이 복구 코드는 연산이 시작되기 이전 상태로 객체를 되돌린다. 디스크 기반의 지속성 자료 구조에 주로 사용되는 기법이다.
  • 객체의 임시 복사본상에서 필요한 연산을 수행하고, 연산이 끝난 다음에 임시 복사본의 내용으로 객체 상태를 바꾸는 것. 데이터를 임시 자료구조에 복사한 다음에 훨씬 신속하게 실행될 수 있는 연산이라면 이 접근법이 자연스럽다. 

 실패 원자성은 일반적으로 권장되는 덕목이지만 언제나 달성할 수 있는 것은 아니다. 예를 들어, 같은 객체를 여러 스레드가 적절한 동기화 없이 동시에 변경할 경우, 객체 상태의 일관성을 깨질 수 있다.

요약

메서드 명세에 포함된 예외가 발생하더라도 객체 상태는 메서드 호출 이전과 동일하게 유지되어야 한다는 것이다. 이 규칙을 지키지 못할 시에는 객체 상태가 어떻게 변하는지 API 문서에 명확하게 서술해야 한다.


+ Recent posts