Combine Functions into Class, 여러 함수를 클래스로 묶기를 알아보자.
요약

코드
function base(aReading) {...}
function taxableCharge(aReading) {...}
function calculateBaseCharge(aReading) {...}class Reading {
base() {...}
taxableCharge() {...}
calculateBaseCharge() {...}
}배경
- 공통 데이터를 중심으로 긴밀하게 엮여있는 함수 무리를 발견하면 클래스로 묶는 것이 좋다.
- 클래스로 묶으면 함수들이 공유하는 공통 환경을 명시적으로 드러낼 수 있다.
- 각 함수에 전달되는 인수도 줄일 수 있다.
- 클래스 말고 변환 함수로 묶는 경우도 있는데, 이는 다음에 알아보자.
절차
- 함수들이 공유하는 공통 데이터 레코드를 캡슐화한다.
- 이게 안되어 있으면 매개변수 객체 만들기부터 한다.
- 공통 레코드를 사용하는 함수 각각을 새 클래스로 옮긴다.
- 이때 공통 레코드를 멤버는 호출문의 인수에서 제거한다.
- 데이터 조작 로직은 함수로 추출하여 클래스로 옮긴다.
예시
reading = {customer: "ivan", quantity: 10, month: 5, year: 2017};
// client 1
const aReading = acquireReading();
const baseCharge = baseRate(aReading.month, aReading.year) * aReading.quantity;
// client 2
const aReading = acquireReading();
const base = (baseRate(aReading.month, aReading.year) * aReading.quantity);
const taxableCharge = Math.max(0, base - taxThreshold(aReading.year));
// client 3
const aReading = acquireReading();
const basicChargeAmount = calculateBaseCharge(aReading);
function calculateBaseCharge(aReading) {
return baseRate(aReading.month, aReading.year) * aReading.quantity;
}- 1, 2, 3에서 기본 요금 계산 공식이 똑같다.
- 그렇다고 3에서 사용한 최상위 코드를 1, 2에서 사용하게 하는 것이 옳을까?
- 데이터 근처에 두는 게 맞다.
- 그렇다면 클래스다.
class Reading {
constructor(data) {
this._customer = data.customer;
this._quantity = data.quantity;
this._month = data.month;
this._year = data.year;
}
get customer() {
return this._customer;
}
get quantity() {
return this._quantity;
}
get month() {
return this._month;
}
get year() {
return this._year;
}
get baseCharge() {
return baseRate(this.month, this.year) * this.quantity;
}
get taxableCharge() {
return Math.max(0, this.baseCharge - taxThreshold(this.year));
}
}
// client 1
const rawReading = acquireReading();
const aReading = new Reading(rawReading);
const baseCharge = aReading.baseCharge;
// client 2
const rawReading = acquireReading();
const aReading = new Reading(rawReading);
const taxableCharge = aReading.taxableCharge;
// client 3
const rawReading = acquireReading();
const aReading = new Reading(rawReading);
const taxableCharge = aReading.taxableCharge;