-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
186 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
# 4장 - 액션에서 계산 빼내기 | ||
|
||
이번 장에서 살펴 볼 내용 | ||
|
||
- 테스트하기 쉽고 재사용 하기 좋은 코드를 만들기 위해 리팩터링 하는 방법 | ||
|
||
```jsx | ||
let shopping_cart = []; // 장바구니 제품과 금액 합계를 담고 있는 전역변수 | ||
let 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(let i = 0; i < shopping_cart.length; i++) { | ||
shopping_cart_total += item.price; | ||
} | ||
set_cart_total_dom(); // 금액 합계를 반영하기 위해 DOM 업데이트 | ||
} | ||
|
||
``` | ||
|
||
## 테스트하기 쉽게 만들기 | ||
|
||
지금 코드는 동작은 하지만, 정확하게 동작하고 있는지 테스트 하기는 어려움. | ||
|
||
- DOM 업데이트와 비즈니스 규칙은 분리 되어야 함 | ||
- 전역변수가 없어야 함 | ||
|
||
## 재사용하기 쉽게 만들기 | ||
|
||
결제팀과 배송팀이 지금 코드를 재사용 하려고 한다면 재사용 불가능함. | ||
|
||
- 장바구니 정보를 전역변수에서 읽어오고 있는데, 결제팀 배송팀은 DB에서 장바구니 정보 읽어와야 됨 | ||
- 결과를 보여주기 위해 DOM을 직접 바꾸고 있지만, 결제팀은 영수증을 배송팀은 운송장을 출력해야 함 | ||
|
||
## 액션과 계산, 데이터를 구분하기 | ||
|
||
함수형 프로그래머는 **암묵적 입력**과 **암묵적 출력**을 부수효과 라고 부른다. | ||
|
||
명시적 입력 | ||
|
||
- 인자 | ||
|
||
암묵적 입력 | ||
|
||
- 인자 외 다른 입력 (전역 변수 읽기) | ||
|
||
명시적 출력 | ||
|
||
- 리턴값 | ||
|
||
암묵적 출력 | ||
|
||
- 리턴값 외 다른 출력 (전역 변수 값 변경) | ||
|
||
```jsx | ||
var total = 0; | ||
|
||
function add_to_total(amount) { // 인자는 명시적 입력 | ||
console.log(total); // 전역 변수를 읽는 것은 암묵적 입력 | ||
total += amount; // 전역 변수를 바꾸는 것은 암묵적 출력 | ||
return total; // 리턴값은 명시적 출력 | ||
} | ||
``` | ||
|
||
⇒ 생각해보니 함수를 작성할 때 인자를 통해 넘겨받지 않고 바로 참조하는 경우가 많았고 (암묵적 입력?) 전역 변수를 바꾸는 행위도 (암묵적 출력)이 많았던 것 같다. | ||
|
||
## 액션에서 계산 빼내기 | ||
|
||
```jsx | ||
// AS IS | ||
function calc_cart_total() { | ||
shopping_cart_total = 0; | ||
// 계산 코드 개선 필요함 | ||
for(let i = 0; i < shopping_cart.length; i++) { | ||
let item = shopping_cart[i]; | ||
shopping_cart_total += item.price; | ||
} | ||
set_cart_total_dom(); | ||
update_shipping_icons(); | ||
update_tax_dom(); | ||
} | ||
``` | ||
|
||
```jsx | ||
// TO BE | ||
function calc_cart_total() { | ||
calc_total(); // 서브루틴 추출하기 => 함수안에 함수가 있을 경우 안에 있는 함수를 서브루틴 이라고 함 | ||
set_cart_total_dom(); | ||
update_shipping_icons(); | ||
update_tax_dom(); | ||
} | ||
|
||
function calc_total() { | ||
shopping_cart_total = 0; // 전역 변수값 바꾸기 => 암묵적 출력 | ||
for(let i = 0; i < shopping_cart.length; i++) { // 전역 변수값 읽기 => 암묵적 입력 | ||
let item = shopping_cart[i]; | ||
shopping_cart_total += item.price; // 전역 변수값 바꾸기 => 암묵적 출력 | ||
} | ||
} | ||
``` | ||
|
||
암묵적 입/출력이 남아있음, 아직 액션임 | ||
|
||
```jsx | ||
// TO BE | ||
function calc_cart_total() { | ||
shopping_cart_total = calc_total(shopping_cart); // 전역 값을 인자로 전달 | ||
set_cart_total_dom(); | ||
update_shipping_icons(); | ||
update_tax_dom(); | ||
} | ||
|
||
function calc_total(cart) { // 명시적 입력 | ||
let total = 0; // 지역변수 => 명시적 출력 | ||
for(let i = 0; i < cart.length; i++) { // 인자로 전달한 값 읽기 => 명시적 입력 | ||
let item = cart[i]; | ||
total += item.price; | ||
} | ||
retrun total; // 지역변수 리턴 => 명시적 출력 | ||
} | ||
``` | ||
|
||
암묵적 입/출력 없앰. | ||
|
||
액션에서 계산 빼기 완료 | ||
|
||
## 액션에서 또 다른 계산 빼내기 2 | ||
|
||
```jsx | ||
// AS IS | ||
function add_item__to_cart(name, price){ | ||
shopping_cart.push({ | ||
name, | ||
price | ||
}); | ||
|
||
calc_cart_total(); | ||
} | ||
``` | ||
|
||
```jsx | ||
// TO BE | ||
function add_item_to_cart(name, price){ | ||
add_item(name, price); | ||
calc_cart_total(); | ||
} | ||
|
||
function add_item(name, price){ | ||
shopping_cart.push({ | ||
// 전역 변수 값 읽기 => 암묵적 입력 | ||
// push() 메서드로 전역 변수 값 변경 => 암묵적 출력 | ||
name, | ||
price | ||
}) | ||
} | ||
``` | ||
|
||
```jsx | ||
// TO BE | ||
function add_item_to_cart(name, price){ | ||
add_item(shopping_cart, name, price); | ||
calc_cart_total(); | ||
} | ||
|
||
function add_item(cart, name, price){ | ||
const new_cart = cart.slice(); // 인자를 통해 전역 변수 값 읽기 => 명시적 입력 | ||
new_cart.push({ // 복사본을 변경 | ||
name, | ||
price | ||
}) | ||
return new_cart; // 복사본 리턴 => 명시적 출력 (카피-온-라이트) | ||
} | ||
``` | ||
|
||
여기서 핵심은 암묵적 입력은 인자로 암묵적 출력은 리턴값으로 바뀐다는 것이고, | ||
인자와 리턴값은 바뀌지 않는 불변값이라는 것이 중요하다. 리턴값이 나중에 바뀐다면 그건 암묵적 출력이다. | ||
|
||
또 인자로 받은 값이 바뀔 수 있다면 그건 암묵적 입력이다. |