diff --git "a/\354\261\225\355\204\260_10/\354\203\201\353\262\224.md" "b/\354\261\225\355\204\260_10/\354\203\201\353\262\224.md" new file mode 100644 index 0000000..9684efd --- /dev/null +++ "b/\354\261\225\355\204\260_10/\354\203\201\353\262\224.md" @@ -0,0 +1,261 @@ +# 10장 - 일급 함수 1 + +## 이번 장에서 살펴볼 내용 + +- 왜 일급 값이 좋은지 +- 문법을 일급 함수로 만드는 방법 +- 고차 함수로 문법을 감싸는 방법 +- 일급 함수와 고차 함수로 사용한 리팩터링 두 개를 살펴보자 + +# 코드의 냄새: 함수 이름에 있는 암묵적 인자 + +함수 본문에서 사용하는 어떤 값이 함수 이름에 나타난다면 **함수 이름에 있는 암묵적 인자**는 코드의 냄새가 됨 + +코드의 냄새를 찾아서 일급 값으로 바꾸면 표현력이 더 좋아짐 + +```jsx +// as-is + +// 문자열이 함수 이름에 그대로 들어있고 비슷한 구조를 가지고 있음 => 암묵적 인자 냄새남 +function setPriceByName(cart, name, price) { + let item = cart(name); + // price 암묵적 인자 냄새 + let newItem = objectSet(item, 'price', price); + let newCart = objectSet(cart, name, newItem); + return newCart; +} + +function setQuantityByName(cart, name, quant) { + let item = cart(name); + let newItem = objectSet(item, 'quantity', quant); + let newCart = objectSet(cart, name, newItem); + return newCart; +} + +function setShippingByName(cart, name, ship) { + let item = cart(name); + let newItem = objectSet(item, 'shipping', ship); + let newCart = objectSet(cart, name, newItem); + return newCart; +} +... +``` + +```jsx +// to-be + +// 필드명을 일급 값으로 만듦 +function setFieldByName(cart, name, field, value) { + // field, value로 명시적인 인자를 추가함 + let item = cart(name); + let newItem = objectSet(item, field, value); + let newCart = objectSet(cart, name, newItem); + return newCart; +} + +// 새로운 인자 사용 +setFieldByName(cart, 'shoe', 'price', 13); +setFieldByName(cart, 'shoe', 'quantity', 3); +setFieldByName(cart, 'shoe', 'shipping', 0); +setFieldByName(cart, 'shoe', 'tax', 2.24); +``` + +일급값은 언어 전체에서 **어디서나 쓸 수 있다는 특징을 가지고 있음** + +### **자바스크립트에서 일급이 아닌 것** + +1. 수식 연산자 +2. 반복문 +3. 조건문 +4. try/catch 블록 + +### **일급으로 할 수 있는 것** + +1. 변수에 할당 +2. 함수의 인자로 넘기기 +3. 함수의 리턴값으로 받기 +4. 배열이나 객체에 담기 + +## **객체와 배열을 너무 많이 쓰게 된다.** + +장바구니와 제품처럼 일반적인 엔티티는 객체와 배열처럼 일반적인 데이터 구조를 사용해야 함 + +데이터를 데이터 그대로 사용하는 것의 중요한 장점은 여러 가지 방법으로 해석할 수 있다는 것이고, 이것이 데이터 지향이라고 하는 중요한 원칙임 + +데이터 지향은 이벤트와 엔티티에 대한 사실을 표현하기 위해 일반 데이터 구조를 사용하는 프로그래밍 형식 + +# **리팩터링: 암묵적 인자를 드러내기** + +함수 이름에 있는 암묵적 인자를 어떻게 명시적인 함수 인자로 바꿀 수 있을까? + +⇒ 암묵적 인자가 일급 값이 되도록 함수에 인자를 추가 + +⇒ 이렇게 하면 잠재적 중복을 없애고 코드의 목적을 더 잘 표현 가능 + +## **반복문 예제: 먹고 치우기** + +```jsx +//준비하고 먹기 +for(let i = 0; i < foods.length; i++){ + let food = foods[i]; + cook(food); + eat(food); +} + +//설거지 하기 +for(let i = 0; i < dishes.length; i++){ + let dish = dishes[i]; + wash(dish); + dry(dish); + putAway(dish); +} +``` + +## 코드를 함수화 하기 + +```jsx +// 준비하고 먹기 +// 함수 이름에서 암묵적 인자 냄새 +function cookAndEatFoods(){ + for(let i = 0; i < foods.length; i++){ + let food = foods[i]; + cook(food); + eat(food); + } +} + +cookAndEatFoods(); + +//설거지 하기 + +function cleanDishes(){ + for(let i = 0; i < dishes.length; i++){ + let dish = dishes[i]; + wash(dish); + dry(dish); + putAway(dish); + } +} + +cleanDishes(); +``` + +## 암묵적 인자 드러내기 + +```jsx +//준비하고 먹기 +function cookAndEatArray(array){ + // 일반적인 이름의 함수명 + // 명시적인 배열 인자 + for(let i = 0; i < array.length; i++){ + let item = array[i]; + cook(item); + eat(item); + } +} + +cookAndEatFoods(foods); +//인자 전달 + +//설거지 하기 +function cleanArray(array){ + // 일반적인 이름의 함수명 + // 명시적인 배열 인자 + for(let i = 0; i < array.length; i++){ + let item = array[i]; + wash(item); + dry(item); + putAway(item); + } +} + +cleanArray(dishes); +//인자 전달 +``` + +## 함수 이름에서 나는 암묵적 인자 냄새 제거하기 + +```jsx +//준비하고 먹기 +function operateOnArray(array, func){ + for(let i = 0; i < array.length; i++){ + let item = array[i]; + func(item); + } +} + +function cookAndEat(food){ + cook(food); + eat(food); +} + +function clean(dish){ + wash(dish); + dry(dish); + putAway(dish); +} + +operateOnArray(foods, cookAndEat); +operateOnArray(dishes, clean); +``` + +# **리팩터링: 함수 본문을 콜백으로 바꾸기** + +1) 본문과 본문의 앞부분과 뒷부분을 구분 +2) 전체를 함수로 빼내기 +3) 본문 부분을 빼낸 함수의 인자로 전달한 함수로 바꾸기 + +```jsx +try{ // 엎부분 + saveUserData(user); // 본문 +} catch (error) { // 뒷부분 + logToSnapErrors(error); +} + +try{ + fetchProduct(ProductId); +} catch (error) { + logToSnapErrors(error); +} +``` + +## 함수로 빼내기 + +```jsx +function withLogging(){ + try{ + saveUserData(user); + } catch (error) { + logToSnapErrors(error); + } +} + +withLogging(); // 함수를 만들고 호출 +``` + +## 콜백으로 빼내기 + +```jsx +function withLogging(func){ + try{ + func() // 인자로 전달받은 함수 호출 + } catch (error) { + logToSnapErrors(error); + } +} + +withLogging(function(){ // 본문 전달 (인라인 정의 방법) + saveUserData(user); +}); +``` + +## **결론 및 요약** + +- 일급 값은 변수에 저장할 수 있고 인자로 전달하거나 함수의 리턴값으로 사용할 수 있다. 일급 값은 코드로 다룰 수 있는 값이다. +- 언어에는 일급이 아닌 기능이 많다. 일급이 아닌 기능은 함수로 감싸 일급으로 만들 수 있다. +- 어떤 언어는 함수를 일급 값처럼 쓸 수 있는 일급 함수가 있다. 일급 함수는 어떤 단계 이상의 함수형 프로그래밍을 하는 데 필요하다. +- 고차 함수는 다른 함수에 인자로 넘기거나 리턴값으로 받을 수 있는 함수다. 고차 함수로 다양한 동작을 추상화할 수 있다. +- **`함수 이름에 있는 암묵적 인자`**는 함수의 이름으로 구분하는 코드의 냄새다. 이 냄새는 코드로 다룰 수 없는 함수 이름 대신 일급 값인 인자로 바꾸는 **`암묵적 인자를 드러내기 리팩터링`**을 적용해서 없앨 수 있다. +- 동작을 추상화하기 위해 **`본문을 콜백으로 바꾸기 리팩터링`**을 사용할 수 있다. 서로 다른 함수의 동작 차이를 일급 함수 인자로 만든다. + +⇒ 근데 회사에서 이렇게 성급한 추상화 하면 바로 리뷰 달림 ㅋㅋ