'immutable 객체'에 해당되는 글 1건

  1. 2016.08.08 Immutable 객체

Immutable(불변) 객체는 수학과 금융 등에서 자주 쓰이는 개념이다.

이 글에서는 켄트 벡의 저서 테스트 주도 개발(TDD)과 켄트 벡의 구현 패턴에 나오는 Money 객체를 예로 들어 설명하도록 하겠다.


정의

Immutable(불변) 객체는 객체 생성 이후 값이 변하지 않는 객체를 말한다. 이는 생성자를 이용한 값 설정 이외의 어떤 갱신 수단도 제공하지 않는다는 것을 의미한다.


특징

정의에서와 마찬가지로 객체 생성 이후에는 값을 변경시킬 수 없다.

또 한가지 특징은 같은 값을 가지는 객체 간에는 동일성(Equality)이 보장된다는 점이다.


이러한 개념이 나오게 된 배경은 바로 실생활에서 사용하는 값에 대한 개념이 바로 그러하기 때문이다. 금융이나 수학에서 자주 쓰이는 개념으로부터 나온 용례를 보면 보다 정확하게 알 수 있다.


용례

1. 100원은 (100원이 계속 존재하는 한) 100원이다. 100원짜리 동전들은 모두 100원이다.

2. PI는 항상 3.141592...이다. PI = PI이다.


Immutable 객체의 정의 및 특징과 마찬가지로 실 생활에서 어떤 값은 항상 그 값으로만 사용된다. 10이 10이었다가 어떤 때에는 20이 되거나 하지 않는다. 그리고 10은 항상 10과 같다. 이러한 동일성은 10이 10인 동안에는 항상 유지된다.

이러한 개념을 구현한 것이 바로 Immutable 객체이다.


실제 구현에 들어가 보자.

켄트 벡의 좋은 예제가 있으므로 그의 자취를 따라가보자. 우리는 Money 객체를 구현할 것이다. Money는 단위(unit)와 값(value)을 갖는다고 가정한다.


Money class 선언

class Money{

    private final String unit;

    private final int value;

    public String getUnit() {

        return unit;

    }

    public int getValue() {

        return value;

    }

}


객체의 외부에서 unit과 value를 확인할 수 있어야 하므로 getter 함수들도 함께 구현해 넣었다.


이제 정의를 만족하도록 더 구현해 넣을 차례다. 우선 생성 이후에는 값이 변경되지 않을 것이므로 생성자를 통해 값을 설정할 수 있도록 해주어야 한다.


class Money{

    public Money(String unit, int value){

        this.unit = unit;

        this.value = value;

    }


이렇게  unit과 value를 매개변수로 받아서 설정할 수 있도록 했다.


그 다음에는 동등성을 확보해야 한다. Java에서 동등성 비교는 equals() 함수를 통해 수행한다. 그런데 Java의 equals() 함수는 객체의 동일성을 비교하는 것이므로 이를 값을 비교하는 것으로 바꾸어 주어야 한다. 그래서 아래와 같이 equals() 함수를 재정의 한다.


class Money{

    @Override

    public boolean equals(Object obj) {

        Money extern = (Money) obj;

        return (extern != null) && unit.equals(extern.unit) && value == extern.value;

    }


여기까지 구현하면 이제 정의를 만족하는 Immutable 객체가 된 것이다. 


하지만 이것만으로 만족하기에는 뭔가 부족하다. 모든 값들은 연산을 할 수 있어야 한다. 5에 5를 더할 수 있어야 하고, 값의 의미에 따라 사칙연산이나 기타 여러 연산을 지원할 수 있어야 한다. 하지만 연산을 수행할 경우 값은 변경된다. 그런데 지금까지 구현한 Immutable 객체에서는 값을 변경할 방법이 없다.(그렇게 하면 값이 변경되므로 Immutable 객체의 정의에 어긋난다.) 그래서 값의 연산을 수행하고 그 결과를 새로운 Immutable 객체 생성을 통해 지원해 주는 함수를 구현해 주어야 한다.


아래 예제는 더하기를 구현한 것이다.


class Money{

    public Money plus(Money added){

        return new Money(unit, value + added.value);

    }


위와 같은 방법을 통해서 하나의 Immutable 객체와 다른 Immutable 객체의 덧셈을 구현한다.(편의상 unit에 대한 동일성 체크는 제외하였다.)


모두 다 구현했다면 아래와 같은 모양이 될 것이다.


최종 구현

class Money{

    private final String unit;

    private final int value;

    public String getUnit() {

        return unit;

    }

    public int getValue() {

        return value;

    }

   

    public Money(String unit, int value){

        this.unit = unit;

        this.value = value;

    }

   

    @Override

    public boolean equals(Object obj) {

        Money extern = (Money) obj;

        return (extern != null) && unit.equals(extern.unit) && value == extern.value;

    }

   

    public Money plus(Money added){

        return new Money(unit, value + added.value);

    }

}


이제 main() 함수를 이용하여 테스트를 해 볼 시간이다.


public static void main(String[] args) {

    Money five = new Money("KRW", 5);

    Money anotherFive = new Money("KRW", 5);

    Money ten = five.plus(five);

    System.out.println(five.equals(anotherFive));

    System.out.println(ten.getValue());

}


5원은 5원과 같아야 하고 5 + 5 = 10원이어야 한다.


용어와 개념은 모르고 있을 때는 전혀 쓸 수 없지만, 알고 있을 때는 매우 유용한 것이다.


Posted by 이세영2
,