Skip to content
Underbleu
GithubLinkedin

1-2. 인트로 - go, then, map, reduce, 명령형과 함수형의 차이

Functional programming1 min read

프로그래머스에서 진행한 유인동님의 ES6로 알아보는 동시성 & 함수형 프로그래밍 강의를 들으며 정리한 내용입니다.

# 인트로

asp, 자바, 루비, iphone sdk등 수많은 언어들을 사용 해왔지만, 기능들을 통채로 외워서 돌아갈 때까지 고치며 만들었다. 그런방식으로 개발해왔더니 9년차까지 공부한 것중 남은게 없었다.

  • 사용해야하는 큰 프레임워크를 익히는게 아니라, 부분 부분을 세세히 볼 줄아는 개발자들이 성공했다.
  • 기술과 framework는 계속 발전하고 바뀐다. 100% 장담하건데, 몇 년 후 리액트는 없을 것이다
  • 기능의 통채를 능숙하게 쓸 수 있는 법을 익히는게 아니라, 그걸 구성하고 있는 근육을 익혀야한다
  • OOP와 FP는 중점을 두고 공부해야할게 다르다
    • OOP는 세계관과 그에 관한 많은 패턴을 이해해야한다 (큰 코드안의 조각들의 관계)
    • FP은 이 코드가 어떤 결과를 낼지만 중요 (작은 코드조각의 평가)

# go()

  • 인자로 받은 함수들이 동기/비동기 인지 상관없이 연산이 되도록 해주는 함수
  • Promise + 숫자 = NaN이 되지 않도록 비동기값에 대한 처리

1 .복잡한 문제를 한 번에 해결하기 (명령형)

1const add10 = a => new Promise(resolve => resolve(a + 10));
2const sub10 = a => a - 10;
3const add5 = a => a + 5;
4const sub5 = a => new Promise(resolve => resolve(a - 5));
5
6function go (a, ...fs) {
7 var b = a;
8 var iter = fs[Symbol.iterator](); // 실행!
9 return function recur(b) {
10 for(const f of iter) {
11 b = f(b);
12 if(b instanceof Promise) return b.then(recur);
13 }
14 return b;
15 } (b);
16}
17
18go(10, add10, sub10, sub5, log) // 5

※ Array의 [Symbol.iterator] 메서드를 한 번 실행시켜줘야 이터러블이 된다 !

2. 복잡한 문제를 작게 쪼개서 해결해보기 (함수형)

  • 몸체가 작기 때문에 결과가 확실하다는 것을 확신할 수 있다
    • 함수형에선 테스트 Case를 먼저 만들고 아주 작은단위의 기능을 코드를 짠다
      -> 정확히 돌아가는지 확인 가능
    • 고로 함수형 프로그래밍은 TDD가 필요없다. 가변적이지 않기 때문에
    • 각자의 역할이 정확히 나눠져 있기 때문에, 코드 수정이 쉽다
  • 문장이 아닌 표현식으로 이루어져 있기 때문에 해석할 필요가 없다

작게 쪼개서 문제를 해결해보자

  1. then(): Promise의 다형성을 해결하고
  2. callR(): 오른쪽(R) 함수에 인자를 담아 call
  3. go(): 실행 go!
1const then = f => a => a instanceof Promise ? a.then(f) : f(a)
2const callR = (b, f) => f(b)
3const go = (a, ...fs) => fs.map(then).reduce(callR, a)
4
5go(10, add10, sub10, sub5, log) // 5

-> map으로 then에 함수들을 넣고, reduce로 함수들을 실행시킨다


# 함수형 프로그래밍에선 TDD가 필요없다?

  • TDD란?
    테스트케이스를 먼저 만들어 놓고, 그에 만족하는 코드를 짜는 방식
    • 컴파일러언어에서
      런타임상황에서 발생할 수 있는 모든 예외상황들을 test case로 많이 만들어 놓고 컴파일러가 찾지못하는 에러를 잡기위함
    • 자바스크립트같은 동적타입에선
      데이터형, 메서드들 간의 type약속들을 test case로 미리 만들어놔, 배포하기 전에 에러를 잡기위함
  • 함수형 프밍에서 테스트케이스가 필요없다는 것이 아니다. 물론 코드를 짜고 테스트를 돌려봐야한다
    -> 다만, 테스트케이스를 먼저짜는게 아니라는 것
  • 작은 단위의 함수를 만들어 놓고 테스트를 완료하면,
    그 이후에 코드에 이 함수를 사용할 시, 이 함수에대한 테스트가 필요없다는것
  • 하지만 객체지향에선 객체-객체 연결할 시, 항상 테스트가 필요하다

# 함수형 프로그래밍을 정의해보자면...?

"순수함수"와 "효과가 있는 함수"를 잘 관리하는 프로그래밍
효과가있는 함수(파괴)를 위험하게 보고 격리하여 관리하는 프로그래밍

  • 순수함수: 그 자체로 연산만 순수하게 함
    ex) add10(a)
  • 효과가 있는함수: 어떤 공간을 파괴할 수 있는
    ex) el.parentNode.removeChild(el)
방법론특징
OOP효과가 있는 함수들을 연관되게 하는 프로그래밍 방법
FP효과가 없는 함수들을 조합하는 프로그래밍 방법

엄청난 논리구조로 코드를 짜놔도, 디버깅하면 결국은 i++이 잘못되있더라...
그래서 막연한 기대감으로 공부하기 시작한게 함수형 프로그래밍이다