Design Patterns

no 

JavaScript

Tiago Vilas Boas

(Montanha)

  • 10 anos de experiência em TI 
  • Desenvolvedor Front-End na CI&T
tiago@artesites.com.br
http://www.artesites.com.br

Legibilidade de um código JS

 

Para facilitar a manutenção e a legibilidade do código, a primeira dica é utilizar apenas um idioma, em nomes de funções, variáveis e comentários.

É importantíssimo seguir um padrão,
mantendo ele do início ao fim do 
projeto. 

/* Comentários */

 

Não é preciso ser o "capitão óbvio". As vezes em métodos específicos se não utiliza-se a documentação automática, não é sempre necessário documentar tudo.

 

    
    // get a specific user
    getUser: function (id) {
        // code here
    }

/* Comentários */

    
    function validate (str) {
        return /^(?:M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})
        |\d+)$/.test(str);
    }
Porém nem todo mundo 
consegue enxergar a Matrix.

 

/* Comentários */

 

"As vezes é melhor não ter comentários e/ou documentação do que tê-los de forma ruim/errônea/desatualizada."


É melhor não ter comentários do que tornar a leitura do código cansativa/entendiante.


"Um bom código não precisa de explicação"

 

Variáveis / Metódos

 

"O mais curto/rápido nem sempre é melhor"

(Dr. Axel Rauschmayer - speaking JavaScript)

 

regularUser melhor que rglrUsr

 

Escrever uma variável mais rápido não significa que ela seja melhor, se precisarmos pensar para decifrar o que aquela variável significa, ela não é uma variável legível !

All of my books are free to read online and will remain so forever!

http://exploringjs.com/

Concisão / Clareza

 

Se o nome do meu método esta muito grande para ser claro, provavelmente ele esta no lugar errado.

Esse método esta fazendo coisas demais.

 

 

    
    function getUserByIdAndSave {
        //code here
    }

Booleans

 

Conforme as boas práticas que estamos acostumados conforme as convenções do Java e uma série de recomendações, os booleanos sempre serão algo que podemos dizer sim ou não para eles. Por mais simples que isso pareça é comum encontrarmos user = false, se user é um objeto não faz sentindo ele receber um parâmetro boolean.

 

 

    
    //Booleans
    isLoggedIn();
    isNumber();
    hasListener;

Clean Code - Robert C. Martin

Functions

 

Funções geralmente são verbos, exceto o construtor. Não faz sentido minha função receber o nome de algo ou o nome que exatamente descreve o código, o nome de minha função deve descrever o seu proposito.

 

    
    render();
    parse();
    $apply();

Collections

 

Quando trabalharmos com coleções devemos sempre utilizar para sua nomeação o plural ou especificar que é uma lista. 

 

    
    companies;
    users;    
    petList;
    

Event Handlers

 

É uma boa prática nomear sempre um handler e não usar uma função anonima. Isso parece ser muito trivial, mas na prática quando precisar debugar seu metódo, ele tendo um nome facilitará e bastante em seu debug.

 

 

    
    onKeyUp;
    onBtnClick;    
    onMouseOut;
    

Event Handlers

   
    var anonymBtn = document.querySelector("#anonym");
    var declaredBtn = document.querySelector("#declared");
    
    
    var myHandler = function () {
        console.log('declared');
    	var a = 1 + b;
    }
    
    anonymBtn.addEventListener('click', function () {
    	console.log('anonym');
    	var a = 1 + b;
    });
    
    declaredBtn.addEventListner('click', myHandler, false);

Globais Everywhere

   
    var User = function () { }

    var Company = function () { }
Se normalmente utilizarmos vários nomes globais, conforme o crescimento de nossa aplicação será muito provável que a partir de um certo ponto, nos falte a criatividade para nomearmos outros nomes em nosso escopo.

Namespace



    window.App = {
      modules: {}
    };
    
    App.modules.user = (function () {
      /* ... */
    })();
    
    App.modules.company = (function () {
      /* ... */
    })();
Os padrões que vimos até então poluem o escopo global da aplicação com a definição de uma série de variáveis. Uma solução é a criação de um namespace de uso específico para os módulos.

Modules

Modularização no desenvolvimento de software é algo imprescindível.
Mencionado já há mais de 10 anos, o mais simples dos padrões de escrita de módulos em JavaScript é o module pattern. O padrão consiste de uma IIFE que retorna um objeto com valores e funções, veja:
    
   var counter = (function () {
      var current = 0;
      return {
        name: "counter",
        next: function () {
          return current + 1;
        },
        isFirst: function () {
          return current == 0;
        }
      };
    })();

https://addyosmani.com/resources/essentialjsdesignpatterns/book/#modulepatternjavascript

Modules

É natural que módulos dependam uns dos outros.

Uma característica importante de um sistema de módulos robusto é a possibilidade de indicar quais são as dependências de um determinado módulo e traçar uma estratégia de carregamento caso esta não esteja disponível.

Ao criar uma função no escopo global, a mesma fica disponível em qualquer ponto da aplicação. Isso pode parecer uma boa ideia no começo, mas conforme a complexidade do software aumenta, mais difícil se torna manter “módulos” no escopo global. 

Notavelmente este modelo não é o ideal, e a comunidade JavaScript evoluiu com algumas boas soluções.

Modules

COMMONJS
Os módulos CJS se tornaram bastante populares por serem a base do padrão adotado pelo Node.js.

O principal impedimento para seu uso atualmente é o não suporte a este padrão nos navegadores.

Existem ferramentas para viabilizar o seu uso em navegadores, inclusive módulos AMD podem internamente utilizar a sintaxe proposta pela especificação de CommonJS.

 

Continua...

Modules

Asyncronous Module Definition (AMD)
Módulos AMD podem ser requisitados, definidos e utilizados a medida que necessários. Nosso contador, se reescrito em AMD, ficaria da seguinte maneira:
    
    define('counter', function () {
      var current = 0;
      function next() {
        return current + 1;
      }
      function isFirst() {
        return current == 0;
      }
      return {
        next: next,
        isFirst: isFirst
      };
    });

Continua...

Considerações finais

MODULES
Um sistema de módulos adequado é a saída para manter a sanidade do seu código JavaScript. 


A respeito das inúmeras soluções, saiba que a escolha de um sistema já padronizado garante o uso de uma solução otimizada para este problema comum.

Se me permite um conselho: prefira sempre um sistema de módulos robusto, é difícil prever o quão complexa uma aplicação poderá se tornar. 


Em outras palavras, escolha entre: AMD, CommonJS modules utilizando ferramentas como Browserify e até mesmo (por sua conta e risco) ES6 modules com ES6 Module Loader.

Design Patterns no JavaScript

By Tiago Vilas Boas

Design Patterns no JavaScript

Design Patterns é um assunto recorrente e muito importante em todas as linguagens.

  • 243