본문 바로가기
우아한테크코스

변경 가능성을 최소화하라

by 자바지기 2022. 3. 25.
반응형

변경 가능성을 최소화하라

 

불변 클래스란? 

인스턴스 내부 값을 수정할 수 없는 클래스

 

불변 클래스를 만들기 위한 5가지 방법

1. 객체의 상태를 변경하는 메서드를 사용하지 않는다. (setter)

2. 클래스를 확장할 수 없도록 한다. - 클래스 final로 선언하기

3. 모든 필드를 final 로 선언한다.

4. 모든 필드를 private로 선언한다. (필드에 직접 접근하는 것 막기)

5. 자신 외에는 내부 가변 컴포넌트에 접근할 수 없다. 즉, 가변 필드는 외부로 반환하면 안된다.

 

 

public final class Complex { 
	private final double re; 
    private final double im; 
    
    public Complex(double re, double im) { 
    	this.re = re; this.rm = im; 
    } 
    
    public double realPart() { 
    	return re; 
    } 
      
    public double imagPart() { 
    	return im; 
    } 
    
    public Complex plus(Complex c) { 
    	return new Complex(re + c.re, im + c.im); 
    }
    
}

 

위와 같은 불변 복소수 클래스에서 복소수의 합을 나타내기 위해 plus 메소드를 사용하는데,

plus 메소드에서는 필드 변수에 직접 값을 더해주는 것이 아닌, 

새로운 객체를 생성하여 반환을 해주고 있다.

 

이처럼 메서드를 적용해 결과를 반환하지만, 피연산자는 그대로인 프로그래밍 패턴을 함수형 프로그래밍 패턴이라고 한다.

 

불변 객체의 장점

 

1. 불변 객체는 단순하다.

클래스가 불변이라면, 영원히 불변으로 남는다.

 

2. 스레드에 안전하여 동기화할 필요 없다.

불변 객체는 다른 스레드에 영향을 주지 않는다. 따라서 안심하고 공유할 수 있다.

 

3. 불변 객체끼리 내부 데이터를 공유할 수 있다.

 

4. 실패 원자성을 제공한다.

실패 원자성 : 메서드에서 예외가 발생한 후에도 그 객체는 여전히 메서드 호출 전과 같은 상태여야한다.

불변 객체의 메서드는 내부 상태를 바꾸지 않으므로 이 성질을 만족한다.

불변 객체의 단점

값이 다르면 반드시 독립된 객체로 만들어야한다.

 

ex)

   public Car move(int number) {
        if (canMove(number)) {
            return new Car(name, position.increase());
        }
        return this;
    }

 

알린의 자동차 경주 코드에서 자동차가 이동할 때마다 새로운 자동차를 생성하였다.

만약 이 자동차의 필드가 엄청 많이 늘어나서, position을 변경될 때 마다 자동차를 새롭게 만드는 데에 큰 비용을 치러야 한다면?

 

불변 클래스를 만드는 또 다른 방법

모든 생성자를 private로 만들고 public 정적 팩터리 메서드를 통해 객체를 생성한다.

 

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

 

public 생성자가 없기 때문에 패키지 밖에서 이 클래스를 확장하는 게 불가능하다. (final 클래스로 선언된 것과 같은 맥락)

 

 

정리

- 클래스는 꼭 필요한 경우가 아니라면 불변이어야 한다.

- 불변으로 만들 수 없는 클래스라도 변경할 수 있는 부분을 최소한으로 줄이자.

- 모든 필드는 private final

- 생성자는 초기화가 완벽히 끝난 상태의 객체를 생성해야한다.

 

반응형

댓글