독서이야기/엘레강트 오브젝트 - 새로운 관점에서 바라본 객체지향

[엘레강트 오브젝트] 3.4 충성스러우면서 불변이거나, 아니면 상수이거나

사랑꾼이야 2023. 3. 22. 23:41
반응형

이 내용은 엘레강트 오브젝트 를 읽으면서 정리한 내용을 포함하고 있습니다.

  • 불변 객체
  • 예시를 알아보자
  • 정리
  • 관련해서 생각해볼 내용

불변 객체

불변 객체의 잘못된 사고 방식

  • 불변 객체의 메서드를 호출할 때마다 상수(constant)처럼 매번 동일한 데이터가 반환되리라 기대
  • 다시 말해서 모든 불변 객체가 문자열 리터럴이나 숫자처럼 동작하리라고 생각

불변 객체의 정의에 따르면 적절해 보일 수도 있겠지만 결론적으로 이런 사고 방식은 틀렸다. 결과가 변하기 때문에 상수는 아니지만, 객체가 대표하는 엔티티에 충성하기 때문에 불변 객체로 분류된다. 객체의 정의는 다음과 같다.

  • 디스크에 있는 파일, 웹 페이지, 바이트 배열, 해시맵, 달력의 월과 같은 실제 엔티티의 대표자

기본적으로 모든 객체는 식별자, 상태, 행동을 포함한다. 디스크에 저장된 파일을 다루기 위해서는 파일의 좌표를 알아야 합니다. 이 좌표를 다른 말로 객체의 상태라고 부른다.

public void echo() {
    File f = new File("/tmp/test.txt");
    System.out.println("File size : %d", file.length());
}
  • 식별자는 f를 다른 객체와 구별
  • 상태는 f가 디스크 상의 파일에 대해 알고 있는 것
  • 행동은 요청을 수신했을 떄 f가 할 수 있는 작업을 나타냄

불변 객체와 가변 객체의 중요한 차이

  • 불변 객체에는 식별자가 존재하지 않으며, 절대로 상태를 변경할 수 없음
  • Java를 포함한 대부분의 OOP 언어에서는 상태가 동일하더라도 서로 다른 객체라고 판단
  • 기본적으로 각 객체는 재정의할 수 있는 자신만의 유일한 식별자를 가짐

불변객체의 특징

  • 불변 객체는 실제 객체가 어디에 존재하고 어떤 방식으로 사용해야 하는지 알고 있다.
  • 불변 객체는 좌표를 알고, 우리는 이 좌표를 상태라고 부른다.
  • 불변 객체는 자신이 대표하는 실세계의 엔티티에게 충성한다.

예시를 알아보자

오직 불변 객체만을 이용해서 컬렉션을 구현하려면 어떻게 해야 할까? 두 가지 방법이 있다.

  • 하나는 상수 리스트(constant list)로 구현하는 방법
  • 다른 하나는 불변 리스트(immutable list)로 구현하는 방법

상수 리스트

class ConstantList<T> {
    private final T[] array;

    ConstantList() {
        this(new T[0]);
    }

    private ConstantList(T[] numbers) {
        this.array = numbers;
    }

    ConstantList with(T number) {
        T[] nums = new T[this.array.length + 1];
        System.arraycopy(this.array, 0, nums, 0, this.array.length);
        nums[this.array.length] = number;
        return new ConstantList(nums);
    }

    Iterable<T> iterate() {
        return Arrays.asList(this.array);
    }
}
  • 상수 리스트에서는 리스트를 수정하거나 새로운 요소를 추가할 때마다 리스트에 포함된 모든 요소의 복사본을 가지는 새로운 리스트를 생성
  • 이런 방식으로 구현된 객체를 불변 객체라고 부르지만, 객체가 대표하는 실제 엔티티와 상태가 동일한 경우에는 불변 대신 상수라는 용어를 사용하는 것을 권장

불변 리스트

class ImmutableList<T> {
    private final List<T> items = LinkedList<T>();

    void add(T number) {
        this.items.add(number);
    }

    Iterable<T> iterate() {
        return Collections.unmodifiableList(this.items);
    }
}

정리

  • 불변 객체와 가변 객체의 중요한 차이는 불변 객체에는 식별자가 존재하지 않으며, 절대로 상태를 변경할 수 없다.
  • 불변 객체는 자신이 대표하는 실세계의 엔티티에게 충성한다.
  • 비즈니스 도메인과 기술 도메인에 무관하게, 게임, 데스크탑 애플리케이션, 모바일 애플리케이션, 엔터프라이즈 시스템을 포함한 어떤 종류의 시스템이라도 전체적으로 불변 객체를 이용해서 설계될 수 있고 설계되어야 한다.

관련해서 생각해볼 내용

반응형