✏️9.5 값을 참조로 바꾸기 (Change Value to Reference)

리팩터링 전

let customer = new Customer(customerData);

리팩터링 후

let customer = customerRepository.get(customerData.id);

🧷 배경

논리적으로 같은 데이터를 물리적으로 복제해 사용할 때 문제는 그 데이터를 갱신해야 할 때다. 이런 경우에 복제된 데이터들을 모두 참조로 바꿔주는게 좋다.

🧷 절차

  1. 같은 부류에 속하는 객체들을 보관할 저장소를 만든다.

  2. 생성자에서 이 부류의 객체들 중 특정 객체를 정확히 찾아내는 방법이 있는지 확인한다.

  3. 호스트 객체의 생성자들을 수정하여 필요한 객체를 이 저장소에서 찾도록 한다. 하나 수정할 때마다 테스트한다.

🧷 예시

// Order 클래스 ...
constructor(data) {
    this._number = data.number;
    this._customer = new Customer(data.customer);    // data.customer가 고객 ID
    // 다른 데이터를 읽어 들인다.
}

get customer() {return this._customer;}

// Customer 클래스 ...
constructor(id) {
    this._id = id;
}

get id() {return this._id;}

물리적으로 똑같은 고객 객체를 사용하고 싶다면 유일한 객체를 저장할 곳이 필요하다.

  1. 저장소 객체를 사용한다.

let _repositoryData;

export function initialize() {
    _repositoryData = {};
    _repositoryData.customers = new Map();
}

export function registerCustomer(id) {
    if (! _repositoryData.customers.has(id))
        __repositoryData.customers.set(id, new Customer(id));
    return findCustomer(id);    
}

export function findCustomer(id) {
    return _repositoryData.customers.get(id);
}
  1. 주문의 생성자에서 올바른 고객 객체를 얻어오는 방법을 찾자.

// Order 클래스 ...
constructor(data) {
    this._number = data.number;
    this._customer = registerCustomer(data.customer);
    // 다른 데이터를 읽어 들인다.
}

get customer() {return this._customer;}

이제 특정 주문과 관련된 고객 정보를 갱신하면 같은 고객을 공유하는 주문 모두에서 갱신된 데이터를 사용하게 된다.

이 예시코드는 생성자 본문이 전역 저장소와 결합된다는 문제가 있다. 전역 객체를 신중히 다뤄야 한다. 이 점이 염려된다면 저장소를 생성자 매개변수로 전달하도록 수정하자.

Last updated