불변 활용하기 : 안정적으로 동작하게 만들기
4.1 재할당
변수에 값을 다시 할당하는것을 재할당
, 파괴적 할당
이라고 한다.
이는 변수의 의미를 바꿔 가독성을 해친다.
- 새로운 변수를 만들어 재할당을 피하는게 가독성과 버그 예방 측면에서 좋다.
- 지역변수와 매개변수 모두 불변으로 만들어 재할당을 막을 수 있다.
4.2 가변으로 인해 발생하는 의도하지 않은 영향
- 변경 가능한 인스턴스 변수
- 참조에 의한 호출(call-by-reference)로 인스턴스를 재사용할 경우, 여러 호출부에서 인스턴스 변수를 재할당할 수 있다.
예상하지 못한 동작을 일으킨다
- 클래스 내부 메소드로 가변 인스턴스 변수 조작하기
- 여러 스레드에서 하나의 인스턴스의 메소드를 통해 인스턴스 변수를 조작할 경우, 의도치 않은 결과가 발생한다.
부수효과
: 함수가 매개변수를 전달받고 값을 리턴하는 역할 이외에 "외부 상태"를 변경하는 것
- 부수효과에서 말하는 외부 상태
- 인스턴스 변수 변경
- 전역 변수 변경
- 매개변수 변경
- I/O 조작
의도치 않은 영향 줄이기
- 함수의 영향 범위 한정하기
- 부수효과가 있는 메소드는 영향 범위를 예측하기 힘들다. 따라서 함수의 영향 범위를 한정하여 버그 발생 가능성을 줄일 수 있다
- 데이터를 매개변수로 받는다
- 상태를 변경하지 않도록 한다
- 값은 함수의 리턴 값으로 돌려준다.
- 부수 효과의 여지를 없앨 수 있도록 인스턴스 변수에 final 수식자를 붙여 불변으로 만들기
- 자연스럽게 부수효과가 있는 메소드를 만들지 못하게 된다.
- 메소드에서 인스턴스 변수를 변경해야할 경우, 변경된 값을 가진 새로운 인스턴스를 반환하도록 한다.
4.3 불변과 가변은 어떻게 다루어야 할까
기본적으로 변수를 불변으로 만들자
- 재할당이 막혀있으므로 변수의 의미가 변하지 않는다 -> 가독성 증가. 혼란 감소
- 클래스의 동작이 안정적이다 -> 결과 예측, 디버깅이 쉽다
- 코드의 영향 범위가 한정적이다 -> 유지보수가 쉽다
자바 뿐만 아니라 다른 프로그래밍 언어에서도 변수를 불변으로 지정하는 키워드들이 존재한다. 최근에 등장하는 언어는 불변이 디폴트가 되도록 만들어지고 있다. 그만큼 불변이라는 성질을 중요하게 여기는 추세다.
가변으로 설계해야하는 경우
- 성능이 매우 중요한 애플리케이션의 경우이다.
- 스코프가 매우 국소적인 곳에서 가변을 사용해도 무관하다. (for-loop에서 카운터 반복 처리)
가변으로 설계할 경우, 상태를 변경하는 메소드를 설계해라
뮤테이터
: 상태를 변화시키는 메소드를 뮤테이터라고 한다
void damage(final int damageAmount) {
final int nextAmount = this.amount - damageAmount;
this.amount = Math.max(MIN, nextAmount);
}
- amount는 음수(잘못된 상태)가 되면 안되므로 0 이상이 되도록(올바른 상태) 값을 변경하는 뮤테이터 메소드로 설계하기 위해 Math.max 함수를 활용한 예시이다.