7. 원본 데이터를 다른 데이터로 변환 작업 수행 시, 원본에 대한 변경이 금지되어 원본 데이터를 참조하는 다른 곳에서의 역 효과 (side effect) 를 미리 방지하고 기능의
재 사용성을 보장 할 수 있다.
특정 변환 작업 행위에 대한 정의를 미리 선언함으로서 입력값에 따라 동일한 처리의 결과를 보장할 수 있다. (테스트의 용이성)
입력값에 따라 동일한 처리에 대한 로직을 그때마다 메모리 할당하는 것이 아닌 이미 처리 방식에 대한 캐시된 정보를 활용하여 처리 성능을 높일 수 있다.
위에서 언급된 특징을 바탕으로 입력값을 맨 나중에 반영함으로서 모듈의 재활용성을 높일 수 있다.
Why using _.chain is a mistake.
lodash/fp의 특징
immutable
auto-curried
iteratee-first data-last methods
7 / 25
8. (_.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
9. 사람들이 시간이 지나면서 가지는 궁금증은 ..
channing이 functional programmiong의 기본 조건이며 이렇게 사용하는 것이 정말 사용성이 좋아지는 것일까?
lodash의 모든 기능을 꼭 _.chain() + .value() 로 사용해야 할 것인가?
상황에 따라 입력값에 따른 단순 true | false만 필요한데?
내가 추가한 새로은 기능의 메소드를 어떻게 _.chain에 추가해야 하지?
성능에 대한 저하는 없을까?
이쯤되면 머리속이 복잡해지고 과연 이방법이 맞는지 고민하게 됨 ^^;
Why using _.chain is a mistake.
과연 이것이 functional programming 일까?
9 / 25
11. 필요할때 사용하는 방식이 파일 크기 및 메모리 사용 크기를 최소화 할 수 있음.
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
12. 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
13. 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
14. 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
15. 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
16. 처리 방식에 대한 선언을 별도의 변수로 저장하여 이를 필요 시 활용함
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
17. 절차형 프로그래밍 방식으로서의 기본 예제
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
18. 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
19. _.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
21. // 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