4장. 액션에서 계산 빼내기
온라인 쇼핑몰 예제 코드 개선하기
-
장바구니에 담겨있는 제품의 금액 합계를 볼 수 있는 기능
-
구매 합계가 20달러 이상이면 무료 배송 아이콘을 띄우는 기능
-
세금 계산하기
개선 전 코드
// 장바구니 구현하기
var shopping_cart = [];
var shopping_cart_total = 0;
function add_item_to_cart(name, price) {
shopping_cart.push({
name: name,
price: price,
});
calc_cart_total();
}
function calc_cart_total() {
shopping_cart_total = 0;
for (var i = 0; i < shopping_cart.length; i++) {
var item = shopping_cart[i];
shopping_cart_total += item.price;
}
set_cart_total_dom();
}
// 무료 배송비 계산하기
function update_shipping_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 (item.price + shopping_cart_total >= 20)
button.show_free_shipping_icon();
else button.hide_free_shipping_icon();
}
}
function calc_cart_total() {
shopping_cart_total = 0;
for (var i = 0; i < shopping_cart.length; i++) {
var item = shopping_cart[i];
shopping_cart_total += item.price;
}
set_cart_total_dom();
update_shipping_icons();
}
// 세금 계산하기
function update_tax_dom() {
set_tax_dom(shopping_cart_total * 0.1);
}
function calc_cart_total() {
shopping_cart_total = 0;
for (var i = 0; i < shopping_cart.length; i++) {
var item = shopping_cart[i];
shopping_cart_total += item.price;
}
set_cart_total_dom();
update_shipping_icons();
update_tax_dom();
}
코드 개선 목표
-
테스트하기 쉽게 만들기
→ DOM 업데이트와 비즈니스 규칙을 분리하기
→ 전역변수 제거하기
-
재사용하기 쉽게 만들기
→ 전역변수에 의존하지 않게
→ DOM을 사용할 수 있는 곳에서 실행한다고 가정하지 않기
→ 함수가 결과값을 리턴
계산 추출을 통해 코드 개선하기
-
계산 코드를 찾아 빼내기
서브루틴 추출하기 리팩토링
: 동작을 유지하며 코드를 바꾸는 것(지역 변수를 입력으로 받고 지역변수를 리턴)함수 추출하기 리팩토링
-
새 함수에 암묵적 입력과 출력 찾기
-
암묵적 입력은 인자로 암묵적 출력은 리턴값으로 바꾸기
← 함수에 암묵적 입력과 출력이 있으면 액션이 되기 때문
function update_tax_dom() {
set_tax_dom(shopping_cart_total * 0.1);
}
// 1. 코드를 선택하고 빼내기
// => 서브루틴 추출하기 (빼낸 코드를 새로운 함수로 만들고 이름 붙이기)
function update_tax_dom_ver1() {
set_tax_dom(calc_tax());
}
function calc_tax_ver1() {
return shopping_cart_total * 0.1;
}
// 2. 암묵적 입력과 출력 찾기
// (1) 암묵적 입력 : shopping_cart_total
// (2) 암묵적 출력 : X
// 3. 입력은 인자로 바꾸고 출력은 리턴값으로 바꾸기
function update_tax_dom_ver2() {
set_tax_dom(calc_tax_ver2(shopping_cart_total));
}
function calc_tax_ver2(amount) {
return amount * 0.1;
}
// -------------------------------------
function update_shipping_icons() {
var buy_buttons = get_buy_buttons_dom();
for (let i = 0; i < buy_buttons.length; i++) {
var button = buy_buttons[i];
var item = button.item;
if (item.price + shopping_cart_total >= 20)
button.show_free_shopping_icon();
else button.hide_free_shipping_icon();
}
}
// 1. 코드를 선택하고 빼내기
// => 서브루틴 추출하기 (빼낸 코드를 새로운 함수로 만들고 이름 붙이기)
function update_shipping_icons_ver1() {
var buy_buttons = get_buy_buttons_dom();
for (let i = 0; i < buy_buttons.length; i++) {
var button = buy_buttons[i];
var item = button.item;
if (gets_free_shipping_ver1()) button.show_free_shopping_icon();
else button.hide_free_shipping_icon();
}
}
function gets_free_shipping_ver1() {
return item.price + shopping_cart_total >= 20;
}
// 2. 암묵적 입력과 출력 찾기
// (1) 암묵적 입력 : shopping_cart_total
// (2) 암묵적 출력 :
// 3. 입력은 인자로 바꾸고 출력은 리턴값으로 바꾸기
function update_shipping_icons_ver2() {
var buy_buttons = get_buy_buttons_dom();
for (let i = 0; i < buy_buttons.length; i++) {
var button = buy_buttons[i];
var item = button.item;
if (gets_free_shipping_ver2(item.price, shopping_cart_total))
button.show_free_shopping_icon();
else button.hide_free_shipping_icon();
}
}
function gets_free_shipping_ver2(item_price, total) {
return item_price + total >= 20;
}
keyPoint
-
액션은 암묵적인 입력 또는 출력을 가지고 있다.
-
계산의 정의에 따르면 계산은 암묵적인 입력이나 출력이 없어야 한다.
-
공유 변수(전역변수 같은)는 일반적으로 암묵적 입력 또는 출력이 된다.
-
암묵적 입력은 인자로 바꿀 수 있다.
-
암묵적 출력은 리턴값으로 바꿀 수 있다.
-
함수형 원칙을 적용하면 액션은 줄어들고 계산은 늘어난다.