하나의 데이터를 놓고 관련된 작동을 하는 함수를 하나의 클래스로 묶어주자. 이러면 함수들이 공유하는 환경을 명확하게 표현할 수 있다.
// 레코드를 캡슐화해야 한다.
const reading = {
customer: "seunghwan",
quantity: 10,
month: 5,
years: 2021,
};
const acquireReading = () => {};
// client1
const aReading = acquireReading();
// baseCharge를 getter를 통해 필요할때 계산되게 해야 한다.
const base = baseRate(aReading.month, aReading.year) * aReading.quantity;
// client2
const aReading = acquireReading();
// basecharge의 계산 로직이 반복되고 있다.
const base = baseRate(aReading.month, aReading.year) * aReading.quantity;
const taxablecharge = Math.max(0, base - taxThreshold(aReading.year));
// client3
const aReading = acquireReading();
// 여기서만 baseCharge를 함수로 호출하고 있다.
const basicChargeAmount = calculateBaseCharge(aReading);
function calculateBaseCharge(aReading) {
return baseRate(aReading.month, aReading.year) * aReading.quantity;
}
위의 코드를 보면, aReading이라는 데이터를 중심으로 2가지의 동작을 클래스의 메서드로 묶어줄 수 있다.
1. baseCharge 계산하는 함수
2. taxableCharge 계산하는 함수
각각을 클래스의 getter로 선언해 사용하는 곳에서는 객체의 프로퍼티로 접근해 결과를 얻을 수 있다.
// 1. 먼저 레코드를 캡슐화해주자.
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;
}
// 2. calculateBaseCharge함수를 클래스 안으로 옮긴 뒤에, 함수 이름을 변경한다.
get baseCharge() {
return baseRate(this.month, this.year) * this.quantity;
}
get taxableCharge() {
return Math.max(0, this.baseCharge - taxThreshold(aReading.year));
}
}
// client3
const rawReading = acquireReading();
const aReading = new Reading(rawReading); // 데이터를 얻은 뒤에, 바로 객체를 만들어주자.
const basicChargeAmount = aReading.baseCharge;
// 위의 Reading클래스를 재사용해서 client1, client2에서 중복되는 코드를 제거한다.
// client1
const rawReading = acquireReading();
const aReading = new Reading(rawReading);
const baseCharge = aReading.baseCharge;
// client2
const rawReading = acquireReading();
const aReading = new Reading(rawReading);
const taxableCharge = Math.max(
0,
aReading.baseCharge - taxThreshold(aReading.year)
);
// client2 - extract function
// 세금 계산 코드를 함수로 추출하자.
function taxableCharge(aReading) {
return aReading.baseCharge - taxThreshold(aReading.year);
}
// client2
const taxableCharge = taxableCharge();
// taxableCharge도 클래스의 메서드로 추출하자.
// client2
const taxableCharge = aReading.taxableCharge;
/**
* getter를 활용해 필요한 시점에 계산해서 클라이언트에 데이터를 전달하도록 했는데,
* 이것의 장점은 데이터가 갱신된다고 하더라도, 계산해서 데이터를 제공하기 때문에 안정적이다.
* */
데이터를 중심으로 연관된 동작을 하는 함수들을 데이터와 함께 클래스로 묶어준다. 이로 인해 응집도를 높일 수 있는 리팩토링이라고 생각한다. 그리고 계산된 로직으로 결과값을 반환함으로써 데이터가 변경되더라도 안정적인 결과를 반환한다는 말에 깊이 공감했다.