diff --git "a/\354\261\225\355\204\260_4/\354\203\201\353\262\224.md" "b/\354\261\225\355\204\260_4/\354\203\201\353\262\224.md" new file mode 100644 index 0000000..7934873 --- /dev/null +++ "b/\354\261\225\355\204\260_4/\354\203\201\353\262\224.md" @@ -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; // 복사본 리턴 => 명시적 출력 (카피-온-라이트) +} +``` + +여기서 핵심은 암묵적 입력은 인자로 암묵적 출력은 리턴값으로 바뀐다는 것이고, +인자와 리턴값은 바뀌지 않는 불변값이라는 것이 중요하다. 리턴값이 나중에 바뀐다면 그건 암묵적 출력이다. + +또 인자로 받은 값이 바뀔 수 있다면 그건 암묵적 입력이다. \ No newline at end of file