$30 off During Our Annual Pro Sale. View Details »

Evolução e futuro do uso de paradigmas no JavaScript

Evolução e futuro do uso de paradigmas no JavaScript

Uma palestra sobre os paradigmas trazidos por bibliotecas e framework como Backbone.js, Angular.js e React. Conheceremos os principais conceitos por trás de programação imperativa, funcional e reativa. Por fim, teremos uma visão clara do quanto evoluímos e o que ainda está por vir na forma e uso da linguagem.

Jean Carlo Emer

September 19, 2015
Tweet

More Decks by Jean Carlo Emer

Other Decks in Programming

Transcript

  1. Paradigmas no
    JavaScript
    evolução e 

    futuro do uso de

    View Slide

  2. jcemer.com
    github.com/jcemer
    twitter.com/jcemer
    speakerdeck.com/jcemer

    View Slide

  3. porto alegre
    talentos.globo.com

    View Slide

  4. Assim como a maioria das
    linguagens, o JavaScript
    atende a uma série de
    paradigmas

    View Slide

  5. Existe confusão e falta de
    entendimento de como os
    paradigmas funcionam e se
    relacionam

    View Slide

  6. Esta é uma palestra
    avançada (e extensa) sobre
    programação e JavaScript

    View Slide

  7. Programando
    de maneira
    imperativa

    View Slide

  8. Solução baseada em uma
    sequência de passos

    View Slide

  9. <br/>var visits = getCookie("counter");<br/>if (visits) {<br/>visits = parseInt(visits) + 1;<br/>document.write("By the way, you have been here " + visits + 
<br/>" times.");<br/>}<br/>else {<br/>visits = 1;<br/>document.write("By the way, this is your first time here.");<br/>}<br/>setCookie("counter", visits);<br/>
    http://www.sislands.com/coin70/week7/counter.htm
    if e else

    View Slide

  10. <br/>// Use single-spaced text for Multiplication table<br/>document.write("<CENTER><BLOCKQUOTE><STRONG><PRE><FONT COLOR='FF0000'">)<br/>var i, j, total; // global variables<br/>for (i = 1; i <= 10; i++) {<br/>for (j = 1; j < 10; j++) {<br/>total = i * j;<br/>total = " " + total //add space before each number<br/>// Add another space before single digits<br/>if (total < 10) total = " " + total;<br/>// Display result<br/>document.write(total);<br/>} // end inner j loop<br/>document.write("<BR>"); // end of line break<br/>} // end of i outer loop<br/>document.write("</FONT></PRE></STRONG></BLOCKQUOTE></CENTER>");<br/>
    http://www.sislands.com/coin70/week2/NestedLoops1.htm
    foooorr

    View Slide

  11. Código que explicitamente
    altera o estado e fluxo de
    execução do programa

    View Slide

  12. Difícil de manter, reusar e
    evoluir

    View Slide

  13. REQ HTML
    CLICK
    JSO
    N
    G
    EN
    E
    ADD
    JSON
    CLICK
    UE
    RATE
    ST

    View Slide

  14. O surgimento de
    tecnologias foi essencial
    para o aperfeiçoamento do
    uso de paradigmas

    View Slide

  15. A comunidade foi o
    principal agente

    View Slide

  16. Orientando a
    objetos com
    protótipos

    View Slide

  17. Solução baseada em um
    conjunto de objetos e troca
    de mensagens entre eles

    View Slide

  18. Prototype.js
    a saudosa

    View Slide

  19. var Person = Class.create({
    initialize: function(name) {
    this.name = name
    },
    say: function(message) {
    return this.name + ': ' + message
    }
    })
    var Pirate = Class.create(Person, {
    say: function($super, message) {
    return $super(message) + ', yarr!'
    }
    })
    http://prototypejs.org/learn/class-inheritance
    herança

    View Slide

  20. Objetos são instâncias de
    um construtor e mantêm
    estado

    View Slide

  21. Todo construtor deve
    possuir uma única
    responsabilidade
    Single responsibility
    principle
    http://www.infoq.com/br/news/2014/02/solid-principios-javascript

    View Slide

  22. Até mesmo as tarefas mais
    simples eram complexas
    utilizando Web APIs

    View Slide

  23. Abstrações
    Orientando a objetos com
    protótipos

    View Slide

  24. new Ajax.Request('/some_url', {
    method:'get',
    onSuccess: function(transport) {
    var response = transport.responseText
    alert("Success! \n\n" + response)
    },
    onFailure: function() {
    alert('Something went wrong...')
    }
    })
    http://prototypejs.org/learn/introduction-to-ajax

    View Slide

  25. getTransport: function() {
    return Try.these(
    function() {return new XMLHttpRequest()},
    function() {return new ActiveXObject('Msxml2.XMLHTTP')},
    function() {return new ActiveXObject('Microsoft.XMLHTTP')}
    ) || false
    }
    Código fonte da versão 1.7.2.0 da Prototype.js
    Operação interna
    do Request

    View Slide

  26. Abstrações servem para
    isolar a complexidade de
    uma operação

    View Slide

  27. Abstrações normalizam e
    delegam operações

    View Slide

  28. Em alguns casos parecia
    mais fácil estender

    View Slide

  29. if (!document.getElementsByClassName) 

    document.getElementsByClassName = function(instanceMethods){
    Código fonte da versão 1.7.2.0 da Prototype.js
    Object.extend(Function.prototype, (function() {
    var ELEMENT_PROTOTYPE = window.HTMLElement ? HTMLElement.prototype :
    Element.prototype;
    Estender document
    Estender construtor de função
    Estender objetos do DOM

    View Slide

  30. DOM extension is one of the
    biggest mistakes Prototype.js has
    ever done.
    http://perfectionkills.com/whats-wrong-with-extending-the-dom
    - Kangax

    View Slide

  31. Modificar objetos que não
    pertencem ao seu código
    não é uma boa prática
    https://www.nczonline.net/blog/2010/03/02/maintainable-javascript-
    dont-modify-objects-you-down-own

    View Slide

  32. jQuery
    a unipresente

    View Slide

  33. $('li').hide()
    http://jqfundamentals.com/chapter/jquery-basics

    View Slide

  34. jQuery possui as mesmas
    operações da Prototype.js
    implementas da maneira
    correta

    View Slide

  35. Encadeando
    operações
    Orientando a objetos 

    com protótipos

    View Slide

  36. $('li')
    .click(function () {
    $(this).addClass('clicked')
    })
    .find('span')
    .attr('title', 'Hover over me')
    http://jqfundamentals.com/chapter/jquery-basics

    View Slide

  37. Encadeamento permite
    executar uma série de
    operações em um
    mesmo objeto

    View Slide

  38. A biblioteca padrão do
    JavaScript é pobre e
    obscura

    View Slide

  39. Aprimorando a
    biblioteca
    padrão
    Orientando a objetos 

    com protótipos

    View Slide

  40. Underscore.js
    a útil

    View Slide

  41. var toString = Object.prototype.toString
    toString.call("Oops") == "[object String]"
    _.isString("Opps")
    Com underscore.js

    View Slide

  42. - keys
    - allKeys
    - values
    - mapObject
    - pairs
    - invert
    - create
    - functions
    - findKey
    - extend
    - extendOwn
    - pick
    - omit
    - defaults
    - clone
    - tap
    - has
    - property
    - propertyOf
    - isEqual
    - isMatch
    - isEmpty
    - isElement
    - isArray
    - isObject
    - isArguments
    - isFunction
    - isString
    - isNumber
    - isFinite
    - isBoolean
    - isDate
    - isRegExp
    - isNaN
    - isUndefined
    - noConflict
    - identity
    - constant
    - noop
    - times
    - random
    - mixin
    - iteratee
    - uniqueId
    - escape
    - unescape
    - result
    - now
    - template
    - isNull
    - matcher

    View Slide

  43. Operações utilitárias 

    são essenciais para um
    código mais legível

    View Slide

  44. Invariavelmente seus
    projetos enfrentarão os
    mesmos problemas

    View Slide

  45. Código
    modularizado
    Orientando a objetos 

    com protótipos

    View Slide

  46. Módulos separam porções
    de código que possuem
    algo em comum

    View Slide

  47. Módulos são coesos,
    desacoplados e reusáveis

    View Slide

  48. Lodash
    a modular

    View Slide

  49. var methods = ['Arguments', 'Function',
    'String', 'Number', 'Date',
    'RegExp', 'Error'];
    _.each(methods, function(name) {
    _['is' + name] = function(obj) {
    return toString.call(obj) ===
    '[object ' + name + ']';
    };
    });
    underscore.js

    View Slide

  50. var isObjectLike = require('./isObjectLike');
    var stringTag = '[object String]';
    var objectProto = global.Object.prototype;
    var objToString = objectProto.toString;
    function isString(value) {
    return typeof value == 'string' || 

    (isObjectLike(value) 

    && objToString.call(value) == stringTag);
    }
    module.exports = isString;
    lang/isString.js

    View Slide

  51. var isObjectLike = require('./isObjectLike');
    var numberTag = '[object Number]';
    var objectProto = global.Object.prototype;
    var objToString = objectProto.toString;
    function isNumber(value) {
    return typeof value == 'number' ||
    (isObjectLike(value)
    && objToString.call(value) == numberTag);
    }
    module.exports = isNumber;
    lang/isNumber.js

    View Slide

  52. DEPENDÊNCIA DUPLICAÇÃO
    VS
    A manutenção do equilíbrio,
    reduzindo a duplicação

    David Chelimsky 

    https://www.youtube.com/watch?v=ugTQF2uw9eg

    View Slide

  53. O importante é definir bem o
    critério de modularização

    View Slide

  54. JavaScript suporta diferentes
    padrões de módulos,
    escolha um
    http://eloquentjavascript.net/10_modules.html

    View Slide

  55. Programando
    de maneira
    funcional

    View Slide

  56. Solução baseada em
    transformação de valores

    View Slide

  57. https://smthngsmwhr.wordpress.com/2014/02/02/eloquent-javascript-
    with-underscore-js
    First-class functions movem o
    JavaScript significativamente
    em direção a FP

    View Slide

  58. Funções podem ser
    passadas e retornados por
    outras funções
    First-class functions

    View Slide

  59. Underscore.js
    a funcional

    View Slide

  60. _.reduce(collection, function(a, b) {
    return a + b
    })
    _.filter(collection, function(n) {
    return (n % 2) === 0
    })
    Livro: Introducing Functional Programming with Underscore.js

    View Slide

  61. Construções funcionais são
    mais fáceis de ler e manter

    View Slide

  62. array.forEach(iteratee)
    array.map(iteratee)
    array.reduce(iteratee, memo)
    array.every(predicate)
    array.find(predicate)
    array.includes(element)
    [...arguments]
    Object.keys(object)
    https://www.reindex.io/blog/you-might-not-need-underscore
    ES 5.1 + ES2015 + ES2016

    View Slide

  63. Ausência de estado
    compartilhado, funções que
    não geram efeito colateral
    Funções puras

    View Slide

  64. Programação funcional vai
    muito além de manipulação
    de coleções

    View Slide

  65. var mult = function (a, b) { return a * b }
    var negate = _.partial(mult, -1)
    var mult2 = _.partial(mult, 2)
    var square = function (n) { return n * n }
    var result = _.compose(negate, mult2, square)

    View Slide

  66. export default store => next => action => {
    // [...]
    }
    https://github.com/rackt/redux/blob/master/examples/real-world/
    middleware/api.js
    export default function (store) {
    return function (next) {
    return function (action) {
    }
    }
    }
    Portando para ES 5.1
    Código original

    View Slide

  67. http://documentcloud.github.io/underscore-contrib#curry
    _.curry(function (store, next, action) {
    // [...]
    })
    Underscore-contrib

    View Slide

  68. Funções precisam aceitar e
    retornar dados imutáveis
    // frozen value type
    const xy = #[ x, y ]
    // functional extension
    const xyz = #[ ...xy, z ]
    https://github.com/sebmarkbage/ecmascript-immutable-data-structures

    View Slide

  69. Mas nem tudo está disponível:
    é preciso aprender a esperar
    por operações assíncronas

    View Slide

  70. getFiles('.', function (files) {
    generateIndex(files, function () {
    generatePosts(files, ready)
    })
    })
    Funções que geram um blog

    View Slide

  71. Programação funcional é
    sobre valores e suas
    relações
    https://blog.jcoglan.com/2013/03/30/callbacks-are-imperative-
    promises-are-functional-nodes-biggest-missed-opportunity

    View Slide

  72. Utilizando
    Promises
    Programando de maneira 

    funcional

    View Slide

  73. Promises são valores que
    representam o possível
    resultado de uma operação
    assíncrona
    http://tableless.com.br/fluxo-de-execucao-assincrono-em-
    javascript-promises

    View Slide

  74. https://blog.jcoglan.com/2011/03/11/promises-are-the-monad-of-
    asynchronous-programming
    pipe([getFiles, generateIndex, generatePosts])
    Promises are the monad of
    asynchronous programming

    View Slide

  75. http://tableless.com.br/fluxo-de-execucao-assincrono-em-javascript-
    promises
    blogParser.start()
    .then(getFiles)
    .then(generateIndex)
    .then(generatePosts)
    Utilizando Promises/A+

    View Slide

  76. Interfaces basicamente
    reagem a eventos vindos do
    usuário e servidor

    View Slide

  77. Programando
    orientado a
    eventos

    View Slide

  78. Solução guiada pela
    ocorrência de eventos
    externos

    View Slide

  79. Web APIs são massivamente
    apoiadas no paradigma de
    eventos

    View Slide

  80. Backbone.js
    o organizado

    View Slide

  81. Backbone.js faz seus dados
    funcionarem igual ao DOM:
    emitindo eventos

    View Slide

  82. Apresentar palestra
    na RubyConf

    View Slide

  83. var TaskView = Backbone.View.extend({
    events: {
    'click [data-check]': 'done'
    },
    done: function (event) {
    this.model.set({done: true})
    },
    initialize: function () {
    this.listenTo(this.model, 'change', this.render)
    },
    render: function () {
    // build task HTML
    }
    })

    View Slide

  84. var TaskView = Backbone.View.extend({
    events: {
    'click [data-check]': 'done'
    },
    done: function (event) {
    this.model.set({done: true})
    },
    initialize: function () {
    this.listenTo(this.model, 'change', this.render)
    },
    render: function () {
    // build task HTML
    }
    })

    View Slide

  85. var TaskView = Backbone.View.extend({
    events: {
    'click [data-check]': 'done'
    },
    done: function (event) {
    this.model.set({done: true})
    },
    initialize: function () {
    this.listenTo(this.model, 'change', this.render)
    },
    render: function () {
    // build task HTML
    }
    })

    View Slide

  86. O DOM não é performático
    quando aplicamos
    modificações a revelia

    View Slide

  87. var TaskView = Backbone.View.extend({
    //...
    initialize: function () {
    this.listenTo(this.model,
    'change:done', this.renderStatus)
    },
    renderStatus: function () {
    var done = this.model.get('done') ? 'ok' : ''
    this.$('[data-status]').text(text)
    }
    });

    View Slide

  88. Neste cenário é que o 

    data-binding fez rir e
    chorar

    View Slide

  89. data
    $scope.Field = "data"
    Data-binding

    View Slide

  90. $scope.Field = "data"
    Two-way data-binding
    data

    View Slide

  91. AngularJS
    o benevolente

    View Slide


  92. {{ done ? 'Ok' : '' }}
    {{ description }}

    app.controller('TaskCtrl', function($scope) {
    $scope.description = 'My task'
    $scope.change = function () {
    $scope.done = true
    }
    })
    HTML?
    JavaScript

    View Slide

  93. http://leoasis.github.io/posts/2014/10/28/think-twice-or-thrice-
    before-using-angular
    http://tutorials.jenkov.com/angularjs/critique.html
    https://medium.com/@mnemon1ck/why-you-should-not-use-
    angularjs-1df5ddf6fc99
    Think Twice (or Thrice)
    Before Using Angular

    View Slide

  94. React.JS
    o vanguardista

    View Slide

  95. var Task = React.createClass({
    getInitialState: function () {
    return {done: false}
    },
    render: function () {
    return
    {this.state.done ? 'Ok' : ''}
    {this.props.description}
    },
    change: function () {
    this.setState({done: true})
    }
    })
    React.render(,
    document.body)
    XML?!

    View Slide

  96. var Task = React.createClass({
    getInitialState: function () {
    return {done: false}
    },
    render: function () {
    return
    {this.state.done ? 'Ok' : ''}
    {this.props.description}
    },
    change: function () {
    this.setState({done: true})
    }
    })
    React.render(,
    document.body)

    View Slide

  97. var Task = React.createClass({
    getInitialState: function () {
    return {done: false}
    },
    render: function () {
    return
    {this.state.done ? 'Ok' : ''}
    {this.props.description}
    },
    change: function () {
    this.setState({done: true})
    }
    })
    React.render(,
    document.body)
    Estado

    View Slide

  98. Manipular e manter o histórico
    dos estados do DOM é difícil. A
    solução é escrever código como
    se você recriasse o DOM toda
    vez que o estado muda
    https://github.com/Matt-Esch/virtual-dom

    View Slide

  99. Já existe um esquema
    gratuito para o fluxo dos
    dados: O DOM
    http://www.code-experience.com/why-you-might-not-need-mvc-with-
    reactjs/
    (os eventos e CSS já utilizam)

    View Slide

  100. Componentes mantêm estado
    e recebem propriedades dos
    seus ancestrais

    View Slide

  101. Set state Dirty Re-render
    React Components
    http://calendar.perfplanet.com/2013/diff/

    View Slide

  102. var newTree = render(data)
    var patches = diff(tree, newTree)
    rootNode = patch(rootNode, patches)
    tree = newTree
    Patch!
    Virtual DOM
    https://github.com/Matt-Esch/virtual-dom

    View Slide

  103. React.js

    View Slide

  104. Ainda precisamos lidar
    com eventos a todo tempo

    View Slide

  105. instant search

    View Slide

  106. var onType = _.debounce(function() {
    $.get('data.json')
    }, 300)
    Buscar depois de 300ms de
    inatividade

    View Slide

  107. var onType = _.debounce(function() {
    $.get('data.json')
    }, 300)
    Buscar depois de 300ms de
    inatividade
    ZzzZzzZz...

    View Slide

  108. E se as request não
    retornarem na ordem?!

    View Slide

  109. Programando
    de maneira
    funcional
    reativa

    View Slide

  110. Solução guiada por streams
    de dados assíncronos

    View Slide

  111. Stream é uma sequência de
    eventos ordenados no
    tempo

    View Slide

  112. var text = $('#input')
    .asEventStream('keydown')
    .debounce(300)
    .map(function(event) {
    return event.target.value
    })
    https://baconjs.github.io
    instant search

    View Slide

  113. text BACO NJS
    Debonced 300ms

    View Slide

  114. var text = $('#input')
    .asEventStream('keydown')
    .debounce(300)
    .map(function(event) {
    return event.target.value
    })
    function movieSearch(query) {
    return Bacon.fromPromise(queryMovie(query))}
    text.flatMap(movieSearch)
    .onValue(function(results) {
    console.log(results)
    })

    View Slide

  115. text BACO NJS
    Query BACO
    Query BACONJS
    Request para a nuvem

    View Slide

  116. text
    results
    BACO NJS
    Query BACO
    Query BACONJS
    Ops

    View Slide

  117. var text = $('#input')
    .asEventStream('keydown')
    .debounce(300)
    .map(function(event) {
    return event.target.value
    })
    function movieSearch(query) {
    return Bacon.fromPromise(queryMovie(query))}
    text.flatMapLatest(movieSearch)
    .onValue(function(results) {
    console.log(results)
    }) latest

    View Slide

  118. text
    results
    BACO NJS
    Query BACO
    Query BACONJS
    x
    http://nullzzz.blogspot.com.br/2012/12/baconjs-tutorial-part-iii-ajax-and-stuff.html

    View Slide

  119. FRP é sobre relações
    dependentes que se estabilizam
    com o passar do tempo
    https://www.zweitag.de/en/blog/technology/functional-reactive-
    programming-frp

    View Slide

  120. View Slide

  121. Conhecer paradigmas e
    práticas vai além de sair
    implementando em projetos

    View Slide

  122. Compreender contextos e
    aplicar as soluções mais
    adequadas é o mais
    importante

    View Slide

  123. só, por favor, 

    não usem o
    maldito ;

    View Slide

  124. @jcemer
    Obrigado

    View Slide