Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Spaghetti com amêndoas: Desenrolando seu código Javascript

Spaghetti com amêndoas: Desenrolando seu código Javascript

Aprenda a utilizar Namespaces, Module Pattern e Almond para organizar melhor seu JavaScript e construir aplicações mais sólidas e escaláveis.

Arthur Gouveia

October 03, 2015
Tweet

More Decks by Arthur Gouveia

Other Decks in Technology

Transcript

  1. Spaguetti com amêndoas Desenrolando seu código Javascript @ArthurGouveia

  2. - O projeto é simples… …na sua cabeça preguiçosa

  3. - É só botar uns “ífi”… …naquele(s) cenário(s) que você

    não previu
  4. Só o Ctrl + F para achar… …aquele trecho de

    código no arquivo de 3000 linhas
  5. - Reutilizar? Ctrl + C e Ctrl + V …pra

    colocar mais massa nesse Spaghetti Code
  6. Os antigos sábios já diziam:

  7. Namespaces
 Module Pattern
 Almond Os ingredientes que faltavam
 para desenrolar

    esse seu
 Spaghetti Code
  8. Arthur Gouveia Software Engineer @ Reliant Solutions

  9. Credits: https://commons.wikimedia.org/wiki/File:Pasta.jpg Namespaces ‘Global scope’ === ‘Danger’ Variable/Function name overwriting

    Third-party scripts, etc
  10. Show me the code var chef = { name: 'Cuca',

    title: 'Mestre' }; whoIsTheChef(); changeChef(); whoIsTheChef(); function whoIsTheChef() { console.log(chef.title + ' ' + chef.name); } /* Random function from third-party script */ function changeChef() { chef = { name: 'Benta', title: 'Dona' }; }
  11. Show me the code > Mestre Cuca > Dona Benta

    var chef = { name: 'Cuca', title: 'Mestre' }; whoIsTheChef(); changeChef(); whoIsTheChef(); function whoIsTheChef() { console.log(chef.title + ' ' + chef.name); } /* Random function from third-party script */ function changeChef() { chef = { name: 'Benta', title: 'Dona' }; }
  12. Show me the code /* Single global object solution */

    var KitchenApp = KitchenApp || {}; KitchenApp.chef = { name: 'Cuca', title: 'Mestre' }; whoIsTheChef(); changeChef(); whoIsTheChef(); function whoIsTheChef() { console.log(KitchenApp.chef.title + ' ' + KitchenApp.chef.name); } /* Random function from third-party script */ function changeChef() { chef = { name: 'Benta', title: 'Dona' }; }
  13. Show me the code > Mestre Cuca > Mestre Cuca

    /* Single global object solution */ var KitchenApp = KitchenApp || {}; KitchenApp.chef = { name: 'Cuca', title: 'Mestre' }; whoIsTheChef(); changeChef(); whoIsTheChef(); function whoIsTheChef() { console.log(KitchenApp.chef.title + ' ' + KitchenApp.chef.name); } /* Random function from third-party script */ function changeChef() { chef = { name: 'Benta', title: 'Dona' }; } Unique ‘use strict’ won’t allow this
  14. Show me the code /* Single global object solution +

    Object Literal Notation */ var KitchenApp = KitchenApp || {}; KitchenApp.Chef = { info: { name: 'Cuca', title: 'Mestre' }, whoIsTheChef: function() { console.log(this.info.title + ' ' + this.info.name); }, changeChef: function(chef_info) { this.info = chef_info; } }; KitchenApp.Chef.whoIsTheChef(); changeChef({ name: 'Ana Maria Braga', title: 'Dona' }); KitchenApp.Chef.whoIsTheChef(); KitchenApp.Chef.changeChef({ name: 'Ana Maria Braga', title: 'Dona' }); KitchenApp.Chef.whoIsTheChef(); /* Random function from third-party script */ function changeChef(chef_info) { chef = chef_info; }
  15. Show me the code > Mestre Cuca > Mestre Cuca

    > Ana Maria Braga /* Single global object solution + Object Literal Notation */ var KitchenApp = KitchenApp || {}; KitchenApp.Chef = { info: { name: 'Cuca', title: 'Mestre' }, whoIsTheChef: function() { console.log(this.info.title + ' ' + this.info.name); }, changeChef: function(chef_info) { this.info = chef_info; } }; KitchenApp.Chef.whoIsTheChef(); changeChef({ name: 'Ana Maria Braga', title: 'Dona' }); KitchenApp.Chef.whoIsTheChef(); KitchenApp.Chef.changeChef({ name: 'Ana Maria Braga', title: 'Dona' }); KitchenApp.Chef.whoIsTheChef(); /* Random function from third-party script */ function changeChef(chef_info) { chef = chef_info; }
  16. Source: http://www.freeimages.com/photo/kitchen-tools-1237100 Module Pattern Single Responsibility Principle Privacy (clean global

    scope) with IIFEs Independency & Reusability Locked state
  17. Module 1. a separable component, frequently one that is interchangeable

    with others, for assembly into units of differing size, complexity, or function. Source: http://dictionary.reference.com/browse/module?s=t
  18. Single Responsibility Principle

  19. Show me the code var ingredientsForPasta = ['Pasta', 'Water', 'Salt'];

    // IIFE - Immediately Invoked Function Expression var KitchenApp = (function() { 'use strict'; // Isolated scope with access to Global console.log(ingredientsForPasta); var ingredientsForSauce = ['Tomato', 'Olive Oil', 'Basil']; console.log(ingredientsForSauce); }()); console.log(ingredientsForPasta); // Error: ingredientsForSauce is not defined // No access to variables defined inside de IIFE console.log(ingredientsForSauce);
  20. Show me the code var ingredientsForPasta = ['Pasta', 'Water', 'Salt'];

    // IIFE - Immediately Invoked Function Expression var KitchenApp = (function() { 'use strict'; // Isolated scope with access to Global console.log(ingredientsForPasta); var ingredientsForSauce = ['Tomato', 'Olive Oil', 'Basil']; console.log(ingredientsForSauce); }()); console.log(ingredientsForPasta); // Error: ingredientsForSauce is not defined // No access to variables defined inside de IIFE console.log(ingredientsForSauce); > [ 'Pasta', 'Water', 'Salt' ] > [ 'Tomato', 'Olive Oil', 'Basil' ] > [ 'Pasta', 'Water', 'Salt' ]
 > ಠ_ಠ
  21. var KitchenApp = KitchenApp || {}; KitchenApp = (function(){ function

    init() { KitchenApp.ChefModule.init(); KitchenApp.ChefModule.getNames(); } return { init: init } }()); KitchenApp.ChefModule = (function(){ 'use strict'; var names; function init() { names = ['Dona Benta', 'Palmirinha', 'Ana Maria Braga']; };// public function getNames(){ console.log(sortChefs()); }; // public function setNames(chefsNames) { names = chefsNames; }; // public function sortChefs() { return names.sort(); } // private return { init: init, getNames: getNames, setNames: setNames } }()); KitchenApp.init(); Show me the code
  22. Show me the code > [ 'Ana Maria Braga', 'Dona

    Benta', 'Palmirinha' ] var KitchenApp = KitchenApp || {}; KitchenApp = (function(){ function init() { KitchenApp.ChefModule.init(); KitchenApp.ChefModule.getNames(); } return { init: init } }()); KitchenApp.ChefModule = (function(){ 'use strict'; var names; function init() { names = ['Dona Benta', 'Palmirinha', 'Ana Maria Braga']; };// public function getNames(){ console.log(sortChefs()); }; // public function setNames(chefsNames) { names = chefsNames; }; // public function sortChefs() { return names.sort(); } // private return { init: init, getNames: getNames, setNames: setNames } }()); KitchenApp.init();
  23. Almond AMD Implementation Define and Require modules
 
 ~3kb of

    cool stuff Source: http://www.freeimages.com/photo/almonds-1317800
  24. Asynchronous Module Definition

  25. Show me the code define('Module.Chef', [], function() { var name

    = 'Palmirinha', salutation = 'Hello, AMD World.'; function intro() { return 'I am ' + name + '. ' + salutation; } return { intro: intro } }); define('Kitchen', ['Module.Chef'], function(chef) { function init() { console.log(chef.intro()); } return { init: init } }); var kitchenApp = require('Kitchen'); kitchenApp.init();
  26. Show me the code > I am Palmirinha. Hello, AMD

    World. define('Module.Chef', [], function() { var name = 'Palmirinha', salutation = 'Hello, AMD World.'; function intro() { return 'I am ' + name + '. ' + salutation; } return { intro: intro } }); define('Kitchen', ['Module.Chef'], function(chef) { function init() { console.log(chef.intro()); } return { init: init } }); var kitchenApp = require('Kitchen'); kitchenApp.init();
  27. Show me the code (function(){ var spaghetti = document.body.dataset.spaghetti; if

    (spaghetti !== undefined) { require('Recipe.' + spaghetti).cook(); } else { document.write('Y u no select a recipe?'); } }()); <body data-spaghetti="Bolognese"> <script type="text/javascript" src="/assets/js/vendor/almond.js"></script> <script type="text/javascript" src="/assets/js/ingredients/groundBeef.js"></script> <script type="text/javascript" src="/assets/js/ingredients/water.js"></script> <script type="text/javascript" src="/assets/js/ingredients/pasta.js"></script> <script type="text/javascript" src="/assets/js/ingredients/tomato.js"></script> <script type="text/javascript" src="/assets/js/ingredients/salt.js"></script> <script type="text/javascript" src="/assets/js/ingredients/oliveOil.js"></script> <script type="text/javascript" src="/assets/js/spaghettis/bolognese.js"></script> <script type="text/javascript" src="/assets/js/kitchenApp.js"></script> </body> kitchenApp.js index.html
  28. Show me the code (function(){ var spaghetti = document.body.dataset.spaghetti; if

    (spaghetti !== undefined) { require('Recipe.' + spaghetti).cook(); } else { document.write('Y u no select a recipe?'); } }()); kitchenApp.js index.html <body data-spaghetti="Bolognese"> <script type="text/javascript" src="/assets/js/vendor/almond.js"></script> <!-- Use a build system (Gulp, Grunt, etc) to concatenate and minify files to a single one --> <script type="text/javascript" src="/assets/js/kitchenApp.js"></script> </body>
  29. Show me the code bolognese.js define('Recipe.Bolognese', [ 'Ingredients.Water', 'Ingredients.Salt', 'Ingredients.Pasta',

    'Ingredients.Tomato', 'Ingredients.GroundBeef', 'Ingredients.OliveOil' ], function(water, salt, pasta, tomato, groundBeef, oliveOil) { var cook = function() { addIngredients([water, salt, pasta, oliveOil]); makeSauce([tomato, salt, oliveOil]); addIngredients([groundBeef]); } var addIngredients = function(ingredients) {} var makeSauce = function(ingredients) {} return { cook: cook }; });
  30. Use sua preguiça a favor de eficiência

  31. Design Patterns

  32. Modularize seu código

  33. Obrigado! @ArthurGouveia