Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Why using _.chain is a mistake

410 views

Published on

lodash/fp를 이용하여 진정한 함수형 프로그래밍을 해보자.

Published in: Education
  • Be the first to comment

  • Be the first to like this

Why using _.chain is a mistake

  1. 1. Why using _.chain is a mistake. 김정기 1 / 25
  2. 2. Why using _.chain is a mistake. 2 / 25
  3. 3. 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
  4. 4. lodash/fp가 lodash 보다  두배 더 빠른 웹팩 빌드/실행 시간과 1.5배 작은 빌드 파일 크기 결과를 얻을 수 있다. Why using  _.chain  is a mistake. 결론 4 / 25
  5. 5. lodash 는 자바스크립트의 다양한 기능을 _ 하위의 유틸리티 형태로 메소드 형태로 제공하며 lodash/fp 는 lodash의 이런 기능을 기반으로 functional programming에 좀 더 친근한 스타일로 아래와 같은 특징을 가지기 위해 재 정리된 모듈이라고 할 수 있다. Why using  _.chain  is a mistake. lodash vs lodash/fp 5 / 25
  6. 6. immutable auto-curried iteratee-first data-last methods Why using  _.chain  is a mistake. lodash/fp의 특징 6 / 25
  7. 7. 원본 데이터를 다른 데이터로 변환 작업 수행 시, 원본에 대한 변경이 금지되어 원본 데이터를 참조하는 다른 곳에서의 역 효과 (side effect) 를 미리 방지하고 기능의 재 사용성을 보장 할 수 있다. 특정 변환 작업 행위에 대한 정의를 미리 선언함으로서 입력값에 따라 동일한 처리의 결과를 보장할 수 있다.  (테스트의 용이성) 입력값에 따라 동일한 처리에 대한 로직을 그때마다 메모리 할당하는 것이 아닌 이미 처리 방식에 대한 캐시된 정보를 활용하여 처리 성능을 높일 수 있다. 위에서 언급된 특징을 바탕으로 입력값을 맨 나중에 반영함으로서 모듈의 재활용성을 높일 수 있다. Why using  _.chain  is a mistake. lodash/fp의 특징 immutable auto-curried iteratee-first data-last methods 7 / 25
  8. 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. 9. 사람들이 시간이 지나면서 가지는 궁금증은 .. channing이 functional programmiong의 기본 조건이며 이렇게 사용하는 것이 정말 사용성이 좋아지는 것일까? lodash의 모든 기능을 꼭  _.chain()  +  .value() 로 사용해야 할 것인가? 상황에 따라 입력값에 따른 단순 true | false만 필요한데? 내가 추가한 새로은 기능의 메소드를 어떻게 _.chain에 추가해야 하지? 성능에 대한 저하는 없을까? 이쯤되면 머리속이 복잡해지고 과연 이방법이 맞는지 고민하게 됨  ^^; Why using  _.chain  is a mistake. 과연 이것이 functional programming 일까? 9 / 25
  10. 10. 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
  11. 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. 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. 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. 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. 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. 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. 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. 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. 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
  20. 20. _.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
  21. 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
  22. 22. Why using  _.chain  is a mistake. webpack 빌드 결과 22 / 25
  23. 23. 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
  24. 24. 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
  25. 25. 고맙습니다 https://nhnent.dooray.com/share/posts/LKrgmIFBTC6H1g4AoVHa3Q 25 / 25

×