반응형
😀 책에서 기억하고 싶은 내용을 써보세요.
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;}
배경
클래스 인라인하기는 클래스 추출하기를 거꾸로 돌리는 리팩터링이다.
- 저자는 더 이상 제 역할을 못 해서 그대로 두면 안 되는 클래스는 인라인해버린다.
- 역할을 옮기는 리팩터링을 하고나니 특정 클래스에 남은 역할이 거의 없을 때 이런 현상이 자주 생긴다. ⇒ 이럴 땐 이 불쌍한 클래스를 가장 많이 사용하는 클래스로 흡수시키자.
두 클래스의 기능을 지금과 다르게 배분하고 싶을 때도 클래스를 인라인한다.
- 클래스를 인라인해서 하나로 합친 다음 새로운 클래스를 추출 하는 게 쉬울 수도 있기 때문 ⇒ 이는 코드를 재구성할 때 흔히 사용하는 방식이기도 하다.
절차
- 소스 클래스의 각 public 메서드에 대응하는 메서드들을 타깃 클래스에 생성한다. 이 메서드들은 단순히 작업을 소스 클래스로 위임해야 한다.
- 소스 클래스의 메서드를 사용하는 코드를 모두 타깃 클래스의 위임 메서드를 사용하도록 바꾼다. 하나씩 바꿀 때마다 테스트한다.
- 소스 클래스의 메서드와 필드를 모두 타깃 클래스로 옮긴다. 하나씩 옮길 때마다 테스트한다.
- 소스 클래스를 삭제하고 조의를 표한다.
예시
배송 추적 정보를 표현하는 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;}
🤔 오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요.
- 결합도가 높고, 복잡하게 엉켜있던 클래스의 메서드를 옮겼던 것이 생각납니다.
- 그에 비해 아무래도 예시의 코드는 간결하기 때문에 옮기기 쉬워 보인다고 느꼈습니다.
🔎 궁금한 내용이 있거나, 잘 이해되지 않는 내용이 있다면 적어보세요.
- 회사를 다니면서 위와 같이 클래스를 인라인 하는 일이 많을지 궁금합니다.
- 개인적으로 많이 없을 것이라고 생각해서 위와 같은 질문이 나온 것 같습니다.
반응형