SlideShare une entreprise Scribd logo
1  sur  25
Télécharger pour lire hors ligne
Why using _.chain is a mistake.
김정기
1 / 25
Why using _.chain is a mistake.
2 / 25
import _ from "lodash";
_.chain([1, 2, 3])
.map(x => [x, x*2])
.flatten()
.sort()
.value();
vs
import map from "lodash/fp/map";
import flatten from "lodash/fp/flatten";
import sortBy from "lodash/fp/sortBy";
import flow from "lodash/fp/flow";
flow(
map(x => [x, x*2]),
flatten,
sortBy(x => x)
)([1,2,3]);
Why using  _.chain  is a mistake.
_.chain을 이용한다면 functional programming이라 할 수 있을까?
lodash
lodash/fp
3 / 25
lodash/fp가 lodash 보다 
두배 더 빠른 웹팩 빌드/실행 시간과 1.5배 작은 빌드 파일 크기 결과를 얻을 수 있다.
Why using  _.chain  is a mistake.
결론
4 / 25
lodash 는 자바스크립트의 다양한 기능을 _ 하위의 유틸리티 형태로 메소드 형태로 제공하며
lodash/fp 는 lodash의 이런 기능을 기반으로 functional programming에 좀 더 친근한 스타일로 아래와 같은 특징을 가지기 위해 재 정리된 모듈이라고 할 수 있다.
Why using  _.chain  is a mistake.
lodash vs lodash/fp
5 / 25
immutable
auto-curried
iteratee-first data-last methods
Why using  _.chain  is a mistake.
lodash/fp의 특징
6 / 25
원본 데이터를 다른 데이터로 변환 작업 수행 시, 원본에 대한 변경이 금지되어 원본 데이터를 참조하는 다른 곳에서의 역 효과 (side effect) 를 미리 방지하고 기능의
재 사용성을 보장 할 수 있다.
특정 변환 작업 행위에 대한 정의를 미리 선언함으로서 입력값에 따라 동일한 처리의 결과를 보장할 수 있다.  (테스트의 용이성)
입력값에 따라 동일한 처리에 대한 로직을 그때마다 메모리 할당하는 것이 아닌 이미 처리 방식에 대한 캐시된 정보를 활용하여 처리 성능을 높일 수 있다.
위에서 언급된 특징을 바탕으로 입력값을 맨 나중에 반영함으로서 모듈의 재활용성을 높일 수 있다.
Why using  _.chain  is a mistake.
lodash/fp의 특징
immutable
auto-curried
iteratee-first data-last methods
7 / 25
(_.flatten(_.map([1, 2, 3], x => [x, x*2]))).sort();
_.chain([1, 2, 3])
.map(x => [x, x*2])
.flatten()
.sort()
.value();
정말 우아하게 코드가 함수형 같이 되었다. 
이제 이렇게 써야겠는걸? (이라고 사람들이 위의 스타일대로 프로그래밍을 시작함)
Why using  _.chain  is a mistake.
Code Refactoring History
1. 기본 절차형 프로그래밍(Precedual Programming)
2. immutable하면서 channing 하게 쓰고 싶다?
8 / 25
사람들이 시간이 지나면서 가지는 궁금증은 ..
channing이 functional programmiong의 기본 조건이며 이렇게 사용하는 것이 정말 사용성이 좋아지는 것일까?
lodash의 모든 기능을 꼭  _.chain()  +  .value() 로 사용해야 할 것인가?
상황에 따라 입력값에 따른 단순 true | false만 필요한데?
내가 추가한 새로은 기능의 메소드를 어떻게 _.chain에 추가해야 하지?
성능에 대한 저하는 없을까?
이쯤되면 머리속이 복잡해지고 과연 이방법이 맞는지 고민하게 됨  ^^;
Why using  _.chain  is a mistake.
과연 이것이 functional programming 일까?
9 / 25
lodash의 전체 모듈 파일 크기는 생각보다 큼 
10%의 기능을 쓰더라도 파일을 전체 로드하며 메모리/디스크 낭비로 이어지게 됨
특히 _.chain 함수를 사용할 경우 (대부분 array like)한 입력을 취하고 아래와 같이 chain object를 리턴하도록 되어 있음
_.chain = (array) => wrap(array, _); // Rough concept of chain
위와 같은 사유로 lodash를 전체 import 하거나 사용자가 원하는 메소드를 부분적으로 global lodash object에 수동 할당해줘야함
import _ from "lodash"; // Import everything.
_.chain([1,2,3]).map(x => x+1).value(); // Use the methods.
Why using  _.chain  is a mistake.
또 한가지의 문제점은?
10 / 25
필요할때 사용하는 방식이 파일 크기 및 메모리 사용 크기를 최소화 할 수 있음.
import chain from "lodash/chain";
import value from "lodash/value";
import map from "lodash/map";
import mixin from "lodash/mixin";
import _ from "lodash/wrapperLodash";
// Add the methods you want. The object generated by chain() will
// now have these methods.
mixin(_, {map: map, chain: chain, value: value});
_.chain([1,2,3]).map(x => x+1).value(); // Use the methods.
하지만 실제 작업을 하면서 사용할 모듈을 살펴보면서 개별 관리를 할 수 있을까?
또한 전역 객체를 수정하는 것이 과연 좋은 선택일까?
_.runInContext로 이러한 불편함을 줄일수 있지만 lodash 전체 파일이 필요함
Why using  _.chain  is a mistake.
_.chain 해결 방안
lodash 파일 크기 줄이기
11 / 25
import filter from "lodash/filter";
const vowels = (array) => filter(array, str => /[aeiou]/i.test(str)
import _ from "lodash";
_.mixin({vowels: vowels});
_.chain(['ab','cd','ef']).vowels().value(); // Use the methods.
Why using  _.chain  is a mistake.
_.chain 해결 방안
개발자가 기능을 확장한다면?
12 / 25
import chain from "lodash/chain";
import value from "lodash/value";
import map from "lodash/map";
import mixin from "lodash/mixin";
import _ from "lodash/wrapperLodash";
mixin(_, {
chain: chain,
value: value,
map: map, // Add existing lodash methods you need.
vowels: vowels, // Add your own lodash methods.
});
_.chain(['ab','cd','ef']).vowels().value(); // Use the methods.
Why using  _.chain  is a mistake.
_.chain 해결 방안
lodash 파일 최소화 결과
13 / 25
import chain from "lodash/chain";
import value from "lodash/value";
import mixin from "lodash/mixin";
import thru from "lodash/thru";
import _ from "lodash/wrapperLodash";
// Have one file that only imports core lodash methods you need.
mixin(_, {
chain: chain,
value: value,
thru: thru,
});
_.chain(['ab','cd','ef']).thru(vowels).value();
Why using  _.chain  is a mistake.
_.chain 해결 방안
lodash에서 사용자 확장 함수는 따로 관리?
14 / 25
Curring + Composition
const add = (a, b) => a + b;
const add5 = _.partial(add, 5); // now `a` is bound (locked-in) to 5
//const add5 = (b) => 5 + b; // this is what it looks like inside
add5(3); // equivalent to invoking add(5, 3);
const _add = (a) => (b) => a + b;
const _add5 = _add(5);
_add5(3); // equivalent to invoking add5(3);
각 함수의 실행 결과에 대한 조합을  compose()  메소드로 대응함
const add8 = (x) => add5(add3(x));
const add8 = compose(add5, add3);
Why using  _.chain  is a mistake.
lodash/fp로 _.chain을 대체 가능
Currying
Composition
15 / 25
처리 방식에 대한 선언을 별도의 변수로 저장하여 이를 필요 시 활용함
import map from "lodash/fp/map";
const squreCalc = map((x) => x*2);
squreCalc([1,2,3]) // eq map((x) => x*2)([1, 2, 3]); // We have this!
Why using  _.chain  is a mistake.
lodash/fp로 적용
16 / 25
절차형 프로그래밍 방식으로서의 기본 예제
sortBy(x => x)(
flatten(
map(x => [x, x*2])
)
)([1, 2, 3]); //arguments inject
import _ from "lodash";
_.chain([1, 2, 3])
.map(x => [x, x*2]).flatten().sort().value();
import map from "lodash/fp/map";
import flatten from "lodash/fp/flatten";
import sortBy from "lodash/fp/sortBy";
import compose from "lodash/fp/compose";
compose(
sortBy(x => x),
flatten,
map(x => [x, x*2])
)([1,2,3]);
compose 함수는 실행 순서에 따라 아래에서 위로 정의를 해야하는 문법으로 구성됨
Why using  _.chain  is a mistake.
Argument Ordering
lodash
lodash/fp compose
17 / 25
import map from "lodash/fp/map";
import flatten from "lodash/fp/flatten";
import sortBy from "lodash/fp/sortBy";
import flow from "lodash/fp/flow";
flow(
map(x => [x, x*2]),
flatten,
sortBy(x => x)
)([1, 2, 3]);
Why using  _.chain  is a mistake.
lodash/fp 로 _.chain과 같은 flow로 처리할 수 있을까?
18 / 25
_.chain() ... .value()  과 달리 No Wrapper Object 이며 추가적인 chain Object가 불필요함
“In fact our composition with flow/flowRight uses chaining internally (when monolithic) to support shortcut fusion in composed methods”
Why using  _.chain  is a mistake.
lodash/fp 결론
19 / 25
_.chain의 동작 방식과는 달리 flow/compose 인자로 반드시 함수의 시리즈로 호출되어야 함.
_.chain([1, 6, 2]).sortBy().value()
AS IS
flow(sortBy)([1, 6, 2]); // eq sortBy([1, 6, 2]); //not work because sortBy is curried and return a function
TO BE
sortBy(/* _.identity */)([1, 6, 2]);
//or
flow(sortBy())([1, 6, 2]);
Why using  _.chain  is a mistake.
lodash/fp Curring에 대한 주의사항
20 / 25
// app-flow.js
import map from "lodash/fp/map";
import flatten from "lodash/fp/flatten";
import sortBy from "lodash/fp/sortBy";
import flow from "lodash/fp/flow";
const run = flow(map(x => [x,x*2]), flatten, sortBy(x=>x));
console.log(run([1,2,3]));
//app-chain.js
import _ from 'lodash';
console.log(_.chain([1,2,3]).map(x => [x,x*2]).flatten().sort().value());
Why using  _.chain  is a mistake.
webpack 빌드 결과
21 / 25
Why using  _.chain  is a mistake.
webpack 빌드 결과
22 / 25
https://www.npmjs.com/package/moment-fp
import * as _ from 'lodash';
const dates = [
[2010, 1, 1],
[2011, 1, 1],
[2012, 1, 1],
[2013, 1, 1]
];
/**
* Using `moment-fp`
*/
import * as M from '../dist/index';
const etc = _.compose(
_.map(M.format('YYYY-MM-DD')),
_.reject(_.compose(_.equals(2011), M.year)),
_.map(M.add(1, 'day')),
_.map(M.moment)
)(dates);
// [ '2010-02-02', '2012-02-02', '2013-02-02' ]
console.log(etc);
Why using  _.chain  is a mistake.
자매품 moment-fp
23 / 25
https://github.com/lodash-archive/lodash-fp 
https://github.com/lodash/lodash/wiki/FP-Guide 
https://medium.com/making-internets/why-using-chain-is-a-mistake-9bc1f80d51ba 
https://www.youtube.com/watch?v=Gj9THIxp7HE
Why using  _.chain  is a mistake.
references
24 / 25
고맙습니다
https://nhnent.dooray.com/share/posts/LKrgmIFBTC6H1g4AoVHa3Q
25 / 25

Contenu connexe

Tendances

Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)beom kyun choi
 
Javascript introduction, dynamic data type, operator
Javascript introduction, dynamic data type, operatorJavascript introduction, dynamic data type, operator
Javascript introduction, dynamic data type, operatorYoung-Beom Rhee
 
스파르탄스터디 E04 Javascript 객체지향, 함수형 프로그래밍
스파르탄스터디 E04 Javascript 객체지향, 함수형 프로그래밍스파르탄스터디 E04 Javascript 객체지향, 함수형 프로그래밍
스파르탄스터디 E04 Javascript 객체지향, 함수형 프로그래밍Young-Beom Rhee
 
프론트엔드스터디 E05 js closure oop
프론트엔드스터디 E05 js closure oop프론트엔드스터디 E05 js closure oop
프론트엔드스터디 E05 js closure oopYoung-Beom Rhee
 
UML distilled 1장 스터디 발표 자료
UML distilled 1장 스터디 발표 자료UML distilled 1장 스터디 발표 자료
UML distilled 1장 스터디 발표 자료beom kyun choi
 
[Live coding] 2회 5 23 (camp-exam_javalanguage)
[Live coding] 2회 5 23 (camp-exam_javalanguage)[Live coding] 2회 5 23 (camp-exam_javalanguage)
[Live coding] 2회 5 23 (camp-exam_javalanguage)동욱 하
 
골때리는 자바스크립트 발표자료
골때리는 자바스크립트 발표자료골때리는 자바스크립트 발표자료
골때리는 자바스크립트 발표자료욱진 양
 
7가지 동시성 모델 - 데이터 병렬성
7가지 동시성 모델 - 데이터 병렬성7가지 동시성 모델 - 데이터 병렬성
7가지 동시성 모델 - 데이터 병렬성HyeonSeok Choi
 

Tendances (8)

Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)
 
Javascript introduction, dynamic data type, operator
Javascript introduction, dynamic data type, operatorJavascript introduction, dynamic data type, operator
Javascript introduction, dynamic data type, operator
 
스파르탄스터디 E04 Javascript 객체지향, 함수형 프로그래밍
스파르탄스터디 E04 Javascript 객체지향, 함수형 프로그래밍스파르탄스터디 E04 Javascript 객체지향, 함수형 프로그래밍
스파르탄스터디 E04 Javascript 객체지향, 함수형 프로그래밍
 
프론트엔드스터디 E05 js closure oop
프론트엔드스터디 E05 js closure oop프론트엔드스터디 E05 js closure oop
프론트엔드스터디 E05 js closure oop
 
UML distilled 1장 스터디 발표 자료
UML distilled 1장 스터디 발표 자료UML distilled 1장 스터디 발표 자료
UML distilled 1장 스터디 발표 자료
 
[Live coding] 2회 5 23 (camp-exam_javalanguage)
[Live coding] 2회 5 23 (camp-exam_javalanguage)[Live coding] 2회 5 23 (camp-exam_javalanguage)
[Live coding] 2회 5 23 (camp-exam_javalanguage)
 
골때리는 자바스크립트 발표자료
골때리는 자바스크립트 발표자료골때리는 자바스크립트 발표자료
골때리는 자바스크립트 발표자료
 
7가지 동시성 모델 - 데이터 병렬성
7가지 동시성 모델 - 데이터 병렬성7가지 동시성 모델 - 데이터 병렬성
7가지 동시성 모델 - 데이터 병렬성
 

Why using _.chain is a mistake