해당 내용은 리팩터링 2판을 읽고 개인적으로 정리한 내용입니다.
저자의 입장
- "목적과 구현을 분리" 하는 방식이 옳다.
- 5-6줄을 넘을 때부터 슬슬 냄새를 풍긴다. (5장의 악취를 말하는 듯)
- 길이가 중요하지 않다. => 켄트 백의 "오리지널 스몰토크 시스템"을 보고 깨달음. => 코드의 목적과 구현의 차이가 큼.
스몰토크는 흑백 시스템으로 강조하는 기능을 사용할 때 highlight() 메소드를 사용하는데, 구현 코드에서 reverse() 만 호출하고 있었다고 한다.
// 이렇게 사용했다는 뜻인듯..
reverse() {
highlight();
}
=> 보통 구문이 짧은 경우는 함수로 분리하지 않는 경우가 많은데 목적이 뚜렷한 경우에는 함수로 분리하는 것이 좋다.
- 서브클래스에서 오버라이드하는 메소드는 인라인 X
장점: 객체의 핵심 데이터 변경 가능, 파생 객체를 일관되게 관리할 수 있음.
// 함수들
function a {}
function b {}
function c {}
// class로 묶기
class A {
a() {}
b() {}
c() {}
}
변환함수: 원본 데이터를 입력받아 필요한 정보를 도출한 뒤, 각각을 출력 데이터의 필드에 넣어서 반환함.
클래스로 묶기 | 변환 함수로 묶기 |
---|---|
원본 데이터가 코드안에서 갱신될 때 적합 | 가공한 데이터를 새로운 레코드에 저장하기 때문에 원본데이터 일관성이 깨질 수 있음. |
// 원본
function priceOrder(product, quantity, shippingMethod) {
const basePrice = product.basePrice * quantity;
const discount = Math.max(quantity - product.discountThreshold, 0) * product.basePrice * product.discountRate;
const shippingPerCase = (basePrice > shippingMethod.feePerCase;
const price = basePrice - discount + shippingPerCase;
return price;
// 단계적 쪼개기 후
// 1. 주문 계산 함수
function priceOrder(product, quantity, shippingMethod) {
const priceData = calculatePricingData(product, quantity);
return applyShipping(priceData, shippingMethod);
}
// 2. 가격데이터를 계산하는 함수
function calculatePricingData(product, quantity) {
const basePrice = product.basePrice * quantity;
const discount = Math.max(quantity - product.discountThreshold, 0) * product.basePrice * product.discountRate;
return (basePrice: basePrice, quantity: quantity, discount: discount);
}
// 3. 배송비 적용 함수
function applyShipping(priceData, shippingMethod) {
const shippingPerCase = (priceData.basePrice > shippingMethod.discountThreshold ? shippingMethod.discountFee: shippingMethod.feePerCase;
const shippingCost = priceData.quantity + shippingPerCase;
return priceData.basePrice - priceData.discount + shippingCost;
}
}