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.

C5df370a883b65279af5a7ca94a5eed7?s=128

Jean Carlo Emer

September 19, 2015
Tweet

Transcript

  1. Paradigmas no JavaScript evolução e 
 futuro do uso de

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

  3. porto alegre talentos.globo.com

  4. Assim como a maioria das linguagens, o JavaScript atende a

    uma série de paradigmas
  5. Existe confusão e falta de entendimento de como os paradigmas

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

    JavaScript
  7. Programando de maneira imperativa

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

  9. <SCRIPT> var visits = getCookie("counter"); if (visits) { visits =

    parseInt(visits) + 1; document.write("By the way, you have been here " + visits + 
 " times."); } else { visits = 1; document.write("By the way, this is your first time here."); } setCookie("counter", visits); </SCRIPT> http://www.sislands.com/coin70/week7/counter.htm if e else
  10. <SCRIPT> // Use single-spaced text for Multiplication table document.write("<CENTER><BLOCKQUOTE><STRONG><PRE><FONT COLOR='FF0000'">)

    var i, j, total; // global variables for (i = 1; i <= 10; i++) { for (j = 1; j < 10; j++) { total = i * j; total = " " + total //add space before each number // Add another space before single digits if (total < 10) total = " " + total; // Display result document.write(total); } // end inner j loop document.write("<BR>"); // end of line break } // end of i outer loop document.write("</FONT></PRE></STRONG></BLOCKQUOTE></CENTER>"); </SCRIPT> http://www.sislands.com/coin70/week2/NestedLoops1.htm foooorr
  11. Código que explicitamente altera o estado e fluxo de execução

    do programa
  12. Difícil de manter, reusar e evoluir

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

    CLICK UE RATE ST
  14. O surgimento de tecnologias foi essencial para o aperfeiçoamento do

    uso de paradigmas
  15. A comunidade foi o principal agente

  16. Orientando a objetos com protótipos

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

    mensagens entre eles
  18. Prototype.js a saudosa

  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
  20. Objetos são instâncias de um construtor e mantêm estado

  21. Todo construtor deve possuir uma única responsabilidade Single responsibility principle

    http://www.infoq.com/br/news/2014/02/solid-principios-javascript
  22. Até mesmo as tarefas mais simples eram complexas utilizando Web

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

  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
  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
  26. Abstrações servem para isolar a complexidade de uma operação

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

  28. Em alguns casos parecia mais fácil estender

  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
  30. DOM extension is one of the biggest mistakes Prototype.js has

    ever done. http://perfectionkills.com/whats-wrong-with-extending-the-dom - Kangax
  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
  32. jQuery a unipresente

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

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

    correta
  35. Encadeando operações Orientando a objetos 
 com protótipos

  36. $('li') .click(function () { $(this).addClass('clicked') }) .find('span') .attr('title', 'Hover over

    me') http://jqfundamentals.com/chapter/jquery-basics
  37. Encadeamento permite executar uma série de operações em um mesmo

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

  39. Aprimorando a biblioteca padrão Orientando a objetos 
 com protótipos

  40. Underscore.js a útil

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

    underscore.js
  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
  43. Operações utilitárias 
 são essenciais para um código mais legível

  44. Invariavelmente seus projetos enfrentarão os mesmos problemas

  45. Código modularizado Orientando a objetos 
 com protótipos

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

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

  48. Lodash a modular

  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
  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
  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
  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
  53. O importante é definir bem o critério de modularização

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

  55. Programando de maneira funcional

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

  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
  58. Funções podem ser passadas e retornados por outras funções First-class

    functions
  59. Underscore.js a funcional

  60. _.reduce(collection, function(a, b) { return a + b }) _.filter(collection,

    function(n) { return (n % 2) === 0 }) Livro: Introducing Functional Programming with Underscore.js
  61. Construções funcionais são mais fáceis de ler e manter

  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
  63. Ausência de estado compartilhado, funções que não geram efeito colateral

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

  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)
  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
  67. http://documentcloud.github.io/underscore-contrib#curry _.curry(function (store, next, action) { // [...] }) Underscore-contrib

  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
  69. Mas nem tudo está disponível: é preciso aprender a esperar

    por operações assíncronas
  70. getFiles('.', function (files) { generateIndex(files, function () { generatePosts(files, ready)

    }) }) Funções que geram um blog
  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

  72. Utilizando Promises Programando de maneira 
 funcional

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

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

  77. Programando orientado a eventos

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

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

  80. Backbone.js o organizado

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

  82. Apresentar palestra na RubyConf

  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 } })
  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 } })
  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 } })
  86. O DOM não é performático quando aplicamos modificações a revelia

  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) } });
  88. Neste cenário é que o 
 data-binding fez rir e

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

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

  91. AngularJS o benevolente

  92. <div ng-controller="TaskCtrl" ng-click="change()"> <span>{{ done ? 'Ok' : '' }}</span>

    {{ description }} </div> app.controller('TaskCtrl', function($scope) { $scope.description = 'My task' $scope.change = function () { $scope.done = true } }) HTML? JavaScript
  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
  94. React.JS o vanguardista

  95. var Task = React.createClass({ getInitialState: function () { return {done:

    false} }, render: function () { return <div onClick={this.change}> {this.state.done ? 'Ok' : ''} {this.props.description}</div> }, change: function () { this.setState({done: true}) } }) React.render(<Task description='My task' />, document.body) XML?!
  96. var Task = React.createClass({ getInitialState: function () { return {done:

    false} }, render: function () { return <div onClick={this.change}> {this.state.done ? 'Ok' : ''} {this.props.description}</div> }, change: function () { this.setState({done: true}) } }) React.render(<Task description='My task' />, document.body)
  97. var Task = React.createClass({ getInitialState: function () { return {done:

    false} }, render: function () { return <div onClick={this.change}> {this.state.done ? 'Ok' : ''} {this.props.description}</div> }, change: function () { this.setState({done: true}) } }) React.render(<Task description='My task' />, document.body) Estado
  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
  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)
  100. Componentes mantêm estado e recebem propriedades dos seus ancestrais

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

  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
  103. React.js ♥

  104. Ainda precisamos lidar com eventos a todo tempo

  105. instant search

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

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

    de 300ms de inatividade ZzzZzzZz...
  108. E se as request não retornarem na ordem?!

  109. Programando de maneira funcional reativa

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

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

  112. var text = $('#input') .asEventStream('keydown') .debounce(300) .map(function(event) { return event.target.value

    }) https://baconjs.github.io instant search
  113. text BACO NJS Debonced 300ms

  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) })
  115. text BACO NJS Query BACO Query BACONJS Request para a

    nuvem
  116. text results BACO NJS Query BACO Query BACONJS Ops

  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
  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

  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
  120. None
  121. Conhecer paradigmas e práticas vai além de sair implementando em

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

    mais importante
  123. só, por favor, 
 não usem o maldito ;

  124. @jcemer Obrigado