액션에서 암묵적 입력과 출력을 줄여 설계를 개선하는 방법에 대해 알아보자.
기존 코드에서 요구사항에 맞지 않은 부분
장바구니에 담긴 제품을 주문할 때 무료 배송인지 확인하는 함수 gets_free_shipping()
→ 장바구니로 무료 배송을 확인하는 게 아니라 제품의 합계와 가격으로 확인하고 있다.
// 인자가 요구사항이랑 맞지 않는다
function gets_free_shipping(total, item_price) {
return item_price + total >= 20
// 장바구니 합계 계산
}
중복된 코드도 존재. 아래 위 코드에 합계에 제품 가격을 더하는 코드가 두 군데나 있다.
function calc_total(cart) {
var total = 0
for(var i = 0; i < cart.length; i++) {
var item = cart[i]
total += item.price
// 장바구니 합계 계산
}
return total
}
함수의 동작을 바꿨으므로 엄밀한 의미의 리팩터링은 아니다.
function update_shopping_icons() {
var buy_buttons = get_buy_buttons_dom()
for (var i = 0; i < buy_buttons.length; i++) {
var button = buy_buttons[i]
var item = button.item
if (gets_free_shipping(shopping_cart_total, item.price)) {
button.show_free_shopping_icon()
} else {
button.hide_free_shopping_icon()
}
}
}
function gets_free_shipping(total, item_price) {
return item_price + total >= 20
}
function update_shopping_icons() {
var buy_buttons = get_buy_buttons_dom()
for (var i = 0; i < buy_buttons.length; i++) {
var button = buy_buttons[i]
var item = button.item
// 새 아이템 추가하여 새 장바구니 만듦
var new_cart = add_item(shopping_cart, item.name, item.price)
if (gets_free_shipping(new_cart)) {
button.show_free_shopping_icon()
} else {
button.hide_free_shopping_icon()
}
}
}
function gets_free_shipping(cart) {
return calc_total(cart) >= 20
}
이제 gets_free_shipping()은 장바구니 자체가 무료배송인지 여부를 알려준다.
원래 있던 장바구니를 직접 변경하지 않고 복사본을 만들었다. 이런 스타일을 카피 온 라이트 copy-on-write라 한다.