Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[박상범] 챕터 4: 액션에서 계산 빼내기 #28

Merged
merged 1 commit into from
May 22, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 186 additions & 0 deletions 챕터_4/상범.md
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; // 복사본 리턴 => 명시적 출력 (카피-온-라이트)
}
```

여기서 핵심은 암묵적 입력은 인자로 암묵적 출력은 리턴값으로 바뀐다는 것이고,
인자와 리턴값은 바뀌지 않는 불변값이라는 것이 중요하다. 리턴값이 나중에 바뀐다면 그건 암묵적 출력이다.

또 인자로 받은 값이 바뀔 수 있다면 그건 암묵적 입력이다.
Loading