Skip to content

Commit

Permalink
상범 10장 (#54)
Browse files Browse the repository at this point in the history
  • Loading branch information
sangbooom authored May 23, 2024
1 parent 9241c2c commit aca428d
Showing 1 changed file with 261 additions and 0 deletions.
261 changes: 261 additions & 0 deletions 챕터_10/상범.md
Original file line number Diff line number Diff line change
@@ -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);
});
```

## **결론 및 요약**

- 일급 값은 변수에 저장할 수 있고 인자로 전달하거나 함수의 리턴값으로 사용할 수 있다. 일급 값은 코드로 다룰 수 있는 값이다.
- 언어에는 일급이 아닌 기능이 많다. 일급이 아닌 기능은 함수로 감싸 일급으로 만들 수 있다.
- 어떤 언어는 함수를 일급 값처럼 쓸 수 있는 일급 함수가 있다. 일급 함수는 어떤 단계 이상의 함수형 프로그래밍을 하는 데 필요하다.
- 고차 함수는 다른 함수에 인자로 넘기거나 리턴값으로 받을 수 있는 함수다. 고차 함수로 다양한 동작을 추상화할 수 있다.
- **`함수 이름에 있는 암묵적 인자`**는 함수의 이름으로 구분하는 코드의 냄새다. 이 냄새는 코드로 다룰 수 없는 함수 이름 대신 일급 값인 인자로 바꾸는 **`암묵적 인자를 드러내기 리팩터링`**을 적용해서 없앨 수 있다.
- 동작을 추상화하기 위해 **`본문을 콜백으로 바꾸기 리팩터링`**을 사용할 수 있다. 서로 다른 함수의 동작 차이를 일급 함수 인자로 만든다.

⇒ 근데 회사에서 이렇게 성급한 추상화 하면 바로 리뷰 달림 ㅋㅋ

0 comments on commit aca428d

Please sign in to comment.