Item 17. 변경 가능성을 최소화하라

심규환·2022년 1월 25일
0

Effective Java

목록 보기
16/29
post-thumbnail

불변 클래스란, 한번 만들어진 인스턴스의 내부 값은 수정할 수 없는 클래스를 말한다.
이 불변 클래스가 가지고 있는 정보는 객체가 파괴되기 전까지 절대 달라지지 않아야 한다. 자바에서 제공하는 불변 클래스의 예로는 String, 기본 타입의 박싱된 클래스, BigInteger, BigDecimal 이 있다.

불변 클래스를 만드는 다섯 가지 규칙이다.

1. 객체의 상태를 변경하는 메서드를 제공하지 마라

2. 클래스를 확장할 수 없도록 하라.
클래스를 확장을 막기 위해선 클래스를 final로 선언하면 된다. 이러면 하위 클래스로 확장이 불가능하고 또 다른 방법은 정적 팩터리를 사용하는 것이다.

3. 모든 필드를 final로 선언하라.
필드를 final로 선언하면 설계자의 의도를 드러낼 수 있게 된다. 그리고 멀티스레드 환경에서의 동기화 문제도 해결된다.

4. 모든 필드를 private로 선언하라
필드를 private로 선언하면 클라이언트에서 해당 값을 수정할 수 없게된다. private가 아닌 public final로 선언해도 불변은 보장하지만 외부에 노출이 되어 내부 표현을 바꾸지 못하게 된다.

5. 자신 외에는 내부의 가변 컴포넌트에 접근할 수 없도록 하라
만약 내부에 가변 참조 필드가 있다면 클라이언트에서 이 필드를 절대 참조할 수 없도록 해야 한다. 접근자 메서드로도 접근할 수 없도록 하여 불변성을 지켜야 한다.

요약하자면 아예 접근조차 못하게 하여 수정할 여지를 주지 말아야 한다. 그러면 불변 객체를 사용함으로써 얻어지는 이점은 무엇일까?

1. 불변 객체는 스레드 안전하여 동기화할 필요가 없다.
위에도 적었듯이 변하지 않는 객체이기 때문에 여러 쓰레드가 동시에 건드려도 멀쩡하다. 그러니 동기화 걱정없이 사용하고 공유할 수 있다.

2. 불변 객체끼리는 내부 데이터를 공유할 수 있다.
값이 변하지 않기 때문에 내부 데이터를 공유하더라도 문제가 생기지 않는다.

3. 객체의 내부 구성요소로 불변 객체를 사용하면 이점이 많다.
값이 바뀌지 않는 구성요소들로 이뤄진 객체라면 그 구조가 아무리 복잡하더라도 불변식을 유지하기 수월하다.

4. 불변 객체는 그 자체로 실패 원자성을 제공한다.
실패 원자성이란, 메서드가 예외를 발생시키더라도 값 자체에 훼손이 없다.

그렇다면 단점은 무엇일까? 바로 값이 다르다면 반드시 독립된 객체를 하나 더 만들어야 한다.
1비트라도 다른 값이 필요하다면 새로 객체를 생성해야 한다. 만약 큰 객체에서 아주 조그마한 변화가 필요하다면 약간의 변화를 주고 새로 생성해야 하기 때문에 큰 비용히 발생한다.

불변 객체를 상속하지 못하게 하는 방법 중에 클래스를 final로 선언하는 것 외에 정적 팩토리를 사용하는 방법이 있다.

public class Complex {
    private final double re;
    private final double im;
    
    private Complex(double re, double im){
    	this.re = re;
        this.im = im;
    }
    public static Complex valueOf(double re, double im){
    	return new Complex(re, im);
    }
}

위와 같이 선언하면 생성자를 private로 막아서 상속 자체를 방지할 수 있고 정적 팩터리로 호출 시, 항상 새로운 객체를 생성해서 주기 때문에 불변을 유지한다.
정적 팩터리로 제공한다면 다수의 구현 클래스를 만들 수 있고 자주 사용하는 값에 객체 캐싱 기능을 사용하여 성능을 끌어올릴 수 있게 된다.

요약해 보겠다.
클래스는 꼭 필요한 경우가 아니라면 불변이어야 한다. 그리고 불변으로 만들 수 없는 클래스라면 변경할 수 있는 부분을 최소한으로 줄이자. 그래야 릴리즈 시, 수정 범위가 줄어들고 보안상의 이점이 있게 된다.
다른 합당한 이유가 없다면 모든 필드는 private final로 선언하자.
생성자는 불변식 설정이 모두 완료된, 초기화가 완벽하게 끝난 객체를 생성해야 한다.

profile
장생농씬가?

0개의 댓글