😀 책에서 기억하고 싶은 내용을 써보세요.

class Person {
  get officeAreaCode() {return this._telephoneNumber.areaCode;}
  get officeNumber()   {return this._telephoneNumber.number;}
}
class TelephoneNumber {
  get areaCode() {return this._areaCode;}
  get number()   {return this._number;}
class TelephoneNumber {
  get officeAreaCode() {return this._officeAreaCode;}
  get officeNumber()   {return this._officeNumber;}

 

 

배경

클래스 인라인하기는 클래스 추출하기를 거꾸로 돌리는 리팩터링이다.

  • 저자는 더 이상 제 역할을 못 해서 그대로 두면 안 되는 클래스는 인라인해버린다.
  • 역할을 옮기는 리팩터링을 하고나니 특정 클래스에 남은 역할이 거의 없을 때 이런 현상이 자주 생긴다. ⇒ 이럴 땐 이 불쌍한 클래스를 가장 많이 사용하는 클래스로 흡수시키자.

두 클래스의 기능을 지금과 다르게 배분하고 싶을 때도 클래스를 인라인한다.

  • 클래스를 인라인해서 하나로 합친 다음 새로운 클래스를 추출 하는 게 쉬울 수도 있기 때문 ⇒ 이는 코드를 재구성할 때 흔히 사용하는 방식이기도 하다.

 

 

절차

  1. 소스 클래스의 각 public 메서드에 대응하는 메서드들을 타깃 클래스에 생성한다. 이 메서드들은 단순히 작업을 소스 클래스로 위임해야 한다.
  2. 소스 클래스의 메서드를 사용하는 코드를 모두 타깃 클래스의 위임 메서드를 사용하도록 바꾼다. 하나씩 바꿀 때마다 테스트한다.
  3. 소스 클래스의 메서드와 필드를 모두 타깃 클래스로 옮긴다. 하나씩 옮길 때마다 테스트한다.
  4. 소스 클래스를 삭제하고 조의를 표한다.

 

예시

배송 추적 정보를 표현하는 TrackingInformation 클래스를 준비

class TrackingInformation {
  get shippingCompany()    {return this._shippingCompany;}  // 배송 회사
  set shippingCompany(arg) {this._shippingCompany = arg;}
  get trackingNumber()     {return this._trackingNumber;}   // 추적 번호
  set trackingNumber(arg)  {this._trackingNumber = arg;}
  get display() {
   return `${this.shippingCompany}: ${this.trackingNumber}`;
 }
}

이 클래스는 배송 클래스의 일부처럼 사용된다.

 

// Shipment 클래스
get trackingInfo() {
  return this._trackingInformation.display;
}
get trackingInformation()  {return this._trackingInformation;}
set trackingInformation(aTrackingInformation) {
  this._trackingInformation = aTrackingInformation;
}

TrackingInformation이 예전에는 유용했을지 몰라도 현재는 제 역할을 못 하고 있으니

Shipment 클래스로 인라인하려 한다.

 

먼저 TrackingInformation의 메서드를 호출하는 코드를 찾는다.

// 클라이언트
aShipment.trackingInformation.shippingCompany = request.vendor;

 

1️⃣ 이처럼 외부에서 직접 호출하는 TrackingInformation의 메서드들을 모조리 Shipment로 옮긴다.

그런데 보통 때의 함수 옮기기와는 약간 다르게 진행해보자. 먼저 Shipment에 위임 함수를 만들고

2️⃣ 클라이언트가 이를 호출하도록 수정하는 것이다.

// Shipment 클래스
set shippingCompany(arg) {this._trackingInformation.shippingCompany = arg;}
// 클라이언트
aShipment.shippingCompany = request.vendor;

 

3️⃣ 다 고쳤다면 TrackingInformation의 모든 요소를 Shipment로 옮긴다.

먼저 display() 메서드를 인라인한다.

// Shipment 클래스
get trackingInfo() {
  return `${this.shippingCompany}: ${this.trackingNumber}`;
}

 

다음은 배송 회사 필드 차례다.

// Shipment 클래스
get shippingCompany()    {return this._shippingCompany;}
set shippingCompany(arg) {this._shippingCompany = arg;}

 

여기서는 이동할 목적지인 Shipment에서 shippingCompany()만 참조하므로 필드 옮기기의 절차를 모두 수행하지 않아도 된다. 그래서 타깃을 참조하는 링크를 소스에 추가하는 단계는 생략한다.

이 과정을 반복하고, 4️⃣ 다 옮겼다면 TrackingInformation 클래스를 삭제한다.

// Shipment 클래스
get trackingInfo() {
  return `${this.shippingCompany}: ${this.trackingNumber}`;
}
get shippingCompany()     {return this._shippingCompany;}
set shippingCompany(arg)  {this._shippingCompany = arg;}
get trackingNumber()      {return this._trackingNumber;}
set trackingNumber(arg)   {this._tackingNumber = arg;}

 

 

 

🤔 오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요.

  • 결합도가 높고, 복잡하게 엉켜있던 클래스의 메서드를 옮겼던 것이 생각납니다.
    • 그에 비해 아무래도 예시의 코드는 간결하기 때문에 옮기기 쉬워 보인다고 느꼈습니다.

 

 

🔎 궁금한 내용이 있거나, 잘 이해되지 않는 내용이 있다면 적어보세요.

  • 회사를 다니면서 위와 같이 클래스를 인라인 하는 일이 많을지 궁금합니다.
    • 개인적으로 많이 없을 것이라고 생각해서 위와 같은 질문이 나온 것 같습니다.

 

 

 

반응형

+ Recent posts