✏️9.4 참조를 값으로 바꾸기 (Change Reference to Value)

리팩터링 전

class Product {
  applyDiscount(arg) {this._price.amount -= arg;}

리팩터링 후

class Product {
  applyDiscount(arg) {
    this._price = new Money(this._price.amount - arg, this._price.currency);
  }

🧷 배경

참조를 복제하여 값으로 바꿔 다루면 자유롭게 활용하기 좋다.

🧷 절차

  1. 후보 클래스가 불변인지, 혹은 불변이 될 수 있는지 확인한다.

  2. 각각의 세터를 하나씩 제거(11.7절)한다.

  3. 이 값 객체의 필드들을 사용하는 동치성(equality) 비교 메서드를 만든다.

    • 대부분의 언어는 이런 상황에 사용할 수 있도록 오버라이딩 가능한 동치성 비교 메서드를 제공한다.

🧷 예시

// Person 클래스 ...
constructor() {
    this._telephoneNumber = new TelephoneNumber();
}

get officeAreaCode() {return this._telephoneNumber.areaCode;}
set officeAreaCode(arg) {this._telephoneNumber.areaCode = arg;}
get officeNumber() {return this._telephoneNumber.number;}
set officeNumber(arg) {this._telephoneNumber.number = arg;}

// TelephoneNumber 클래스 ...
get areaCode() {return this._areaCode;}
set areaCode(arg) {this._areaCode = arg;}
get number() {return this._number;}
set number(arg) {this._number = arg;}
  1. 전화 번호를 불변으로 만든다.

  2. 필드들의 세터들만 제거하면 된다. → 세터로 설정하던 두 필드를 생성자에서 입력받아 설정하도록 한다.

// TelephoneNumber 클래스 ...
constructor(areaCode, number) {
    this._areaCode = _areaCode;
    this._number = number;
}

// Person 클래스 ...
get officeAreaCode() {return this._telephoneNumber.areaCode;}
set officeAreaCode(arg) {
    this._telephoneNumber.areaCode = new TelephoneNumber(arg, this.officeNumber);
}
get officeNumber() {return this._telephoneNumber.number;}
set officeNumber(arg) {
    this._telephoneNumber.number = new TelephoneNumber(this.officeAreaCode, arg);
}

전화번호가 불변이 되었으니, 값 객체로 인정받기 위해 동치성을 값 기반으로 평가해야 한다.

javascript 에서는 참조 기반 동치성을 값 기반 동치성으로 대체하는 언어나 라이브러리가 없어 equals를 직접 작성한다.

Last updated