Slide 1

Slide 1 text

FAÇA PROGRAMAÇÃO FUNCIONAL COM JAVASCRIPT CODANDO MENOS o que não fazer para alcançar um código mais simples e funcional

Slide 2

Slide 2 text

2 @_rchaves_

Slide 3

Slide 3 text

os exemplos serão mostrados em JS, mas eles podem ser adaptados pra praticamente qualquer linguagem de programação que possa passar funções ou lambdas como argumentos 3

Slide 4

Slide 4 text

as primeiras duas regras são as mais importantes, as outras são uma mera consequência dessas 4

Slide 5

Slide 5 text

Premissa: com menos features, nós podemos ter um código mais funcional e (discutivelmente) mais simples 5

Slide 6

Slide 6 text

MUTABILIDADE É UMA FEATURE 6 x = x + 1 x - x = 1 0 = 1 n o n s e n s e !

Slide 7

Slide 7 text

NÃO USE MUTABILIDADE 7 Não use Use var const let no-var + no-let* + no-mutation* *usando eslint-plugin-immutable ESLint

Slide 8

Slide 8 text

EXEMPLOS 8 let myValues = [ 1, 2, 3 ]; myValues.push(4); return myValues; const myValues = [ 1, 2, 3 ]; return [ ...myValues, 4];

Slide 9

Slide 9 text

9 let foo = { name: 'Foo' }; foo.age = 32; return foo; const foo = { name: 'Foo' }; return { ...foo, age: 32 }; EXEMPLOS

Slide 10

Slide 10 text

AVOID VOID 10 doThis(); doThat(); return foo; eslint-plugin-no-implicit-side-effects ESLint result = myFn(); Não use Use

Slide 11

Slide 11 text

11 addItemsToCart(); savePurchase(); updateScreen(); const updatedCart = addItems(cart, items); const purchase = savePurchase(updatedCart); return view(purchase); EXEMPLOS

Slide 12

Slide 12 text

EXEMPLOS 12 addItemsToCart(); savePurchase(); updateScreen(); return view(savePurchase(addItems(cart, items)));

Slide 13

Slide 13 text

EXEMPLOS 13 array.push(5); object.key = 'five'; myObj.setFoo('bar'); i++; post('http://url', {}); return [ ...array, 5 ]; return { ...object, key: 5 }; return new MyObj('bar'); return i + 1; return post('http://url', {});

Slide 14

Slide 14 text

CAN’T TOUCH THIS 14 this params () => {} .bind(this) *no-this *usando eslint-plugin-immutable ESLint doesn’t create this! Não use Use

Slide 15

Slide 15 text

EXEMPLOS 15 function distance () { return Math.abs(this.x - this.y); } const distance = (x, y) => Math.abs(x - y);

Slide 16

Slide 16 text

EXEMPLOS 16 const name = user.getFormattedName(); const name = getFormattedName(user);

Slide 17

Slide 17 text

NÃO USE FOR/EACH 17 for reduce map .forEach filter no-for-loops* + no-implicit-side-effects** *usando bahmutov/eslint-rules ESLint **usando eslint-plugin-no-implicit-side-effects Não use Use

Slide 18

Slide 18 text

EXEMPLOS 18 let uppercaseNames = []; for (let i = 0; i < names.length; i++) { let uppercaseName = toUpperCase(names[i]); uppercaseNames.push(uppercaseName); } return uppercaseNames; return names.map(toUppercase);

Slide 19

Slide 19 text

EXEMPLOS 19 let total = 0; items.forEach((item) => { total += item.price; }); return total; return items.reduce((total, item) => total + item.price , 0);

Slide 20

Slide 20 text

EXEMPLOS 20 let names = []; let result = []; list.forEach((item) => { const uppercasedName = toUpperCase(item.name); if (names.indexOf(uppercasedName) < 0) { names.push(uppercasedName); result.push({ name: uppercasedName, count: 1 }); } else { result[names.indexOf(uppercasedName)].count++; } }); return result; // input: [{name: ‘foo'}, {name: 'foo'}, {name: 'foo'}, {name: 'bar'}, {name: 'bar'}, {name: 'baz'}] // output: [{name: 'FOO', count: 3}, {name: 'BAR', count: 2}, {name: 'BAZ', count: 1}]

Slide 21

Slide 21 text

EXEMPLOS 21 const mapToUpperCase = list => list.map(item => ({ ...item, name: toUpperCase(item.name) })); const countRepeated = (list, value) => list.reduce((total, item) => item.name === value.name ? total + 1 : total, 0); const addRepeatCount = list => list.map(item => ({ ...item, count: countRepeated(list, item) })); const removeDuplicates = list => list.filter((item, index) => list.indexOf(list.find(x => x.name === item.name)) === index); return removeDuplicates(addRepeatCount(mapToUpperCase(list)));

Slide 22

Slide 22 text

NÃO USE IF SEM ELSE 22 just if if/else if/return ternary none :( ESLint Não use Use

Slide 23

Slide 23 text

23 if (foo) { return 'bar'; } if (foo) { return 'bar'; } return 'baz'; if (foo) { return 'bar'; } else { return 'baz'; } foo ? 'bar' : 'baz'; EXEMPLOS

Slide 24

Slide 24 text

NÃO USE CLASSES 24 class functions *no-class *usando eslint-plugin-no-class ESLint Não use Use

Slide 25

Slide 25 text

25 class Person { getFormattedName (person) { return person.name.toUpperCase(); } save (person) { return post('http://saveName', { name: person.name }); } } const getFormattedName = (person) => person.name.toUpperCase(); const save = (person) => post('http://saveName', { name: person.name }); EXEMPLOS

Slide 26

Slide 26 text

26 class ListComponent extends React.Component { render () { return
    { this.listItems() }
; } listItems () { return this.props.items.map(item =>
  • { item.name }
  • ); } } const listComponent = (props) =>
      { listItems(props.items) }
    ; const listItems = (items) => items.map(item =>
  • { item.name }
  • ); EXEMPLOS

    Slide 27

    Slide 27 text

    OU VOCÊ PODE USAR ELM vamos remover todas essas features!

    Slide 28

    Slide 28 text

    OBRIGADO! ALGUMA PERGUNTA? bit.ly/pf-codando-menos

    Slide 29

    Slide 29 text

    NO OPTIONAL ARGS (BONUS) 29 optional args for changing behaviour specialized functions none :( ESLint function composition currying default args for common scenarios Não use Use

    Slide 30

    Slide 30 text

    30 const getPrices = (items, onlyOdds = true) => { const prices = items.map(item => item.price); if (onlyOdds) { return prices.filter(price => price % 2 !== 0); } return items; }; const getPrices = items => items.map(item => item.price); const getOddPrices = items => getPrices(items).filter(price => price % 2 !== 0); EXEMPLOS

    Slide 31

    Slide 31 text

    31 const increasePrices = (items, by = 5) => items.map(item => ({ ...item, price: item.price + by })); increasePrices(list1); increasePrices(list2); increasePrices(list3, 10); const increasePrices = amount => items => items.map(item => ({ ...item, price: item.price + amount })); const increasePricesBy5 = increasePrices(5); const increasePricesBy10 = increasePrices(10); increasePricesBy5(list1); increasePricesBy5(list2); increasePricesBy10(list3); EXEMPLOS