✏️7.3 기본형을 객체로 바꾸기 (Replace Primitive with Object)

리팩터링 전

orders.filter(o => "high" === o.priority || "rush" === o.priority);

리팩터링 후

orders.filter(o => o.priority.higherThan(new Priority("normal")))

🧷 배경

필자는 데이터를 표현하는 전용 클래스를 정의하는 편이며 프로그램이 커질 수록 유용하다고 함.

단순한 정보를 숫자나 문자열 같은 간단한 데이터 항목으로 표현하지만 나중에 포매팅이나 지역코드 추출 같은 특별한 동작이 필요해질 때 드는 노력을 줄일 수 있다.

🧷 절차

  1. 아직 변수를 캡슐화 하지 않았다면 캡슐화한다.

  2. 단순한 값 클래스를 만든다. 생성자는 기존 값을 인수로 받아서 저장하고, 이값을 반환하는 게터를 추가한다.

  3. 정적 검사를 수행한다.

  4. 값 클래스의 인스턴스를 새로 만들어서 필드에 저장하도록 세터를 수정한다. 이미 있다면 필드의 타입을 적절히 변경한다.

  5. 새로 만든 클래스의 게터를 호출한 결과를 반환하도록 게터를 수정한다.

  6. 테스트한다.

  7. 함수 이름을 바꾸면 원본 접근자의 동작을 더 잘 드러낼 수 있는지 검토한다. ➡️ 참조를 값으로 바꾸거나 값을 참조로 바꾸면 새로 만든 객체의 역할(값 또는 참조 객체)이 더 잘 드러나는지 검토한다.

🧷 예시

// Order 클래스...
constructor(data){
  this.priority = data.priority;
  // 나머지 초기화 코드 생략
}
  
// 클라이언트...
highPriorityCount = orders.filter(o => "high" === o.priority || "rush" === o.priority).length;
  1. 변수 캡슐화

// Order 클래스...
get priority() {return this._priority;}
set priority(aString) {this._priority = aString;}
  1. 우선순위 속성을 표현하는 값 클래스 Priority를 만든다 해당 클래스는 표현할 값을 받는 생성자와 그 값을 문자열로 반환하는 변환함수로 구성된다.

class Priority{
  constructor(value) {this._value = value;}
  toString() {return this._value;}
}  
  1. 만든 Priority 클래스를 사용하도록 접근자들을 수정한다.

// Order 클래스...
get priority()  {return this._priority.toString();}
set priority(aString)  {this._priority = new Priority(aString);}
  1. 현재 게터가 반환하는 값은 우선순위 자체가 아니라 우선순위를 표현하는 문자열이다. 그래서 아래와 같이 함수 이름(priorityString)을 바꿔준다.

// Order클래스...
get priorityString() {return this._priority.toString();}
set priority(aString) {this._priority = new Priority(aString);}
  
// 클라이언트...
highPriorityCount = orders.filter(o => 
  "high" === o.priorityString || "rush" === o.priorityString).length;

String이 붙어서 유형을 쉽게 알 수 있다면 세터의 이름은 그대로 둬도 좋다.

Last updated