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: 액션에서 계산 빼내기 #22

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
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
80 changes: 80 additions & 0 deletions 챕터_3/이유희.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@

### 액션, 계산, 데이터 구분하기

- 코드를 읽을 때 액션과 계산, 데이터 중 어떤 것에 속하는지 잘 살펴보자
- 숨어있는 액션까지 잘 찾자
- 하나의 액션을 데이터, 계산, 액션으로 쪼개자
- 계속 나누다 보면 풍부한 모델링이 가능해진다
- 냉장고 확인하기
- 냉장실 확인하기
- 냉동실 확인하기
- 구입하기
- 장바구니 담기
- 계산하기

> 하나의 액션을 분리하는 과정이 OOP에서 단일책임원칙을 위해 메서드를 분리해 내는 과정과 비슷하다 생각함
> 액션, 계산, 데이터는 분리를 어떻게 할 것인가의 기준을 제공해주는 느낌

- 데이터는 데이터만 조합할 수 있다
- 데이터는 다른 영향을 주지 않는 그냥 데이터다. 데이터를 찾는 일을 먼저 해야 한다.
- 데이터를 찾았다면 동작에 대해 많은 것을 알 수 있다
> 데이터를 찾았다면 동작에 대해 많은 것을 알 수 있다는 부분은 아직 감이 안 온다


### 데이터

- 이벤트에 대한 사실. 일어난 일의 결과를 기록한 것
- 의미 있게 처리한 입력 장치로부터 얻은 정보
- 데이터의 의미는 데이터 구조로 담을 수 있다. 데이터 구조로 도메인을 표현할 수 있다
- 데이터의 장점
- 직렬화
- 동일성 비교
- 자유로운 해석. 반드시 해석이 필요하다는 점은 단점이다


### 계산

- 입력값으로 출력값을 만드는 것
- 실행 시점과 횟수에 관계없이 항상 같은 입력값에 대해 같은 출력값으로 돌려준다

- 액션보다 계산이 좋은 이유
- 테스트하기 쉽다
- 조합해서 더 큰 계산을 만들 수 있다
- 동시에 실행, 실행 횟수 등을 신경쓰지 않아도 된다
- 단점
- 계산과 액션은 실행하기 전에 어떤 일이 발생할지 알 수 없다


### 액션

- 외부 세계에 영향을 주거나 받는 것.
- 실행 시점과 횟수에 의존한다

#### 액션은 코드 전체로 퍼진다

- 액션을 부르는 함수도 액션이 된다
- 그 함수를 부르는 다른 함수도 액션이 된다
- 액션은 반드시 사용해야 하지만 제어하기 어렵때문에 가능한 적고, 작게 잘 제어해서 사용하는게 중요
- 이상적인 액션 구조
- 액션이 외부 세계와 상호작용하는 것을 제한
- 내부에 계산과 데이터만 있고 가장 바깥쪽에 액션이 있는 구조 -> 18장 어니언 아키텍처

> 어니언 아키텍처 기대된다

- 함수형 프로그래머는 액션이 호출 시점과 횟수에 덜 의존하도록 만드는 기술을 적용한다

#### 액션의 형태

- 함수 호출
- 메서드 호출
- 생성자
- 부르는 시점에 따라 다른 값을 가진다면 액션
- 표현식
- 공유 변수 라면 읽을 때마다 변경될 가능성이 있으므로
- 변수 참조
- 속성 참조
- 배열 참조
- 상태
- 변경 가능하면 액션이다. 다른 코드에 영향을 주기 때문

> 전반적으로 코드를 액션, 계산, 데이터로 분리하는 과정은 예측 가능하며 유지보수 하기 쉬운 코드로 귀결된다고 생각함
130 changes: 130 additions & 0 deletions 챕터_4/이유희.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@


1. 테스트하기 쉽게 만들기
2. 재사용하기 쉽게 만들기
3. 액션과 계산, 데이터를 구분하기
4. 함수에는 입력과 출력이 있다
1. 테스트와 재사용성은 입출력과 관련이 있다
2. 액션에서 계산 빼내기



### 문제점

- `cart * 0.01` 를 테스트하기 위해서 `update_tax()`를 테스트해야 한다

```javascript
function update_tax(){
set_tax(cart * 0.01)
}
```

- `update_tax()`에 요구사항이 추가되면 더 복잡해진다

- 개선
- 테스트하기 쉽게 만들자
- 재사용하기 쉽게 만들자


### 함수형 사고로 리팩토링하기


#### 액션, 계산, 데이터로 구분하기

- 코드를 액션, 계산, 데이터로 분류해보자


#### 함수에는 입력과 출력이 있다

- 입력: 함수가 계산을 하기 위한 외부 정보
- 출력: 함수 밖으로 나오는 정보나 어떤 동작
- 함수 호출의 목적: 어떤 결과가 필요해서

```javascript

var total = 0;
// 입력
function add_to_total(amount){
// 전역변수 읽기는 입력이다
// 콘솔에 뭔가 찍는 것은 출력이다
console.log("toatl :" + total);
// 전역변수를 바꾸는 것은 출력이다
total += amount;
// 리턴값은 출력이다
return total;
}
```

- 입력
- 암묵적 입력
- 인자 외 다른 입력
- ex) 전역변수를 읽는 것
- 명시적 입력
- 인자
- 출력
- 암묵적 출력
- 리턴값 외 다른 출력
- ex) 콘솔에 찍는 것, 전역변수를 바꾸는 것
- 명시적 출력
- 리턴값

- ***함수에 암묵적 입력과 출력이 있으면 액션이 된다*** *
- 암묵적 입력과 출력은 명시적으로 바꾸자



#### 테스트와 재사용성은 입출력과 관련 있다

- 전역변수가 없어야 하며 의존하지 않아야 한다
- 함수가 결괏값을 리턴해야 한다

> update 함수를 void로 선언하면 테스트하기 어려웠다. void에서 리턴 타입이 있게 변경하면 테스트하기 쉬워진다.<br>
> 근데 리턴 타입을 도메인 자체로 하면 객체가 오래 떠돌아 다닐 위험성이 있어 사이드 이펙트가 발생할듯?<br>
> 업데이트한 속성의 결과 값을 원시형으로 리턴하거나 래퍼 또는 vo를 생성해서 리턴하는게 나을까?<br>


> 생각해보기
> 동작을 유지하면서 코드를 바꾸는 것은 어떤 장점이 있을까?<br>
> 동작을 유지하면서 코드를 바꾸면 코드 변경의 사이드 이펙트 없이 수정하는 것이라 위험 부담이 줄어든다.<br>
> 리팩토링한 코드가 기존 동작대로 동작하는게 검증되면 구조를 바꾸거나 패턴으로 추상화 하면서 점진적 개선이 가능하지 않을까나



#### 액션에서 계산 빼내기

- 액션에서 계산에 해당하는 코드를 분리한다
- 입력값은 인자로 출력값은 리턴값으로 바꾼다

```javascript
// 암묵적 출력 명시적으로 변경하기

// 개선 전
function calc_cart_total(){
// calc_total() 내부에서 전역변수를 갱신하는 코드는 암묵적 출력이다
calc_total();
}
// 개선 후
function calc_cart_total(){
// calc_total()의 리턴값은 이제 명시적 출력이다
shopping_cart_total = calc_total();
}
```



```javascript
// 암묵적 입력 명시적으로 변경하기

// 개선 전
function calc_cart_total(){
// calc_total() 내부에서 전역변수나 객체 프로퍼티를 읽는 코드는 암묵적 입력
calc_total();
}
// 개선 후
function calc_cart_total(){
// calc_total(shopping_cart) 인자로 입력하면 명시적 입력이다
shopping_cart_total = calc_total(shopping_cart);
}
```

>
Loading