Locaweb Style

Documentação

Saiba todas as features que te ajudarão a produzir sistemas mais rapidamente.

Práticas de JavaScript

Se quiser contribuir com JavaScript, siga essas práticas

Pattern JavaScript

O pattern utilizado por nós é o Revealing Module Pattern.

As principais vantagens de manter este padrão são:

  1. Consistência de código;
  2. Melhores práticas;
  3. Escalabilidade;
  4. Fácil manutenção;
  5. Uniformidade entre projetos.

A ideia é que o código mantenha unidade, seja ele escrito por uma ou várias pessoas, dentro de um projeto e entre projetos diferentes, diminuindo o tempo de aprendizado.

As regras a seguir propoem um padrão mínimo para desenvolvimento. O mais importante é manter a consistência de estilo de código. O que for escolhido como estilo para o seu projeto deverá ser seguido em todos os arquivos.

Padrões de escrita

Identação: utilizamos 2 espaços, mas o mais importante é seguir um estilo único. Nunca misture espaços e tabs em único arquivo. Para facilitar incluímos no projeto um arquivo de configuraçao de editores, o ".editorconfig", saiba mais sobre ele em editorconfig.org

Existem plugins para vários editores, no nosso time usamos:

Sintaxe: para separaçao dos blocos de código, utilizamos o estilo1TBS, por exemplo:

1
2
3
4
5
if ( x < 0 ) {
  console.log( x )
} else {
  console.log( y )
}

Observe os alinhamentos, quebras de linhas, posição das chaves e espaços entre variáveis e operadores.

Revealing Module Pattern

Para melhorar a organização dos arquivos, funções, performance e diminuir a chance de erros e conflitos, adotamos o Revealing Module Pattern do Christian Heilmann .

As vantagens desse pattern são: organização, clareza, performance, expõe publicamente apenas as funções e variáveis que se deseja e namespace único evitando sobrescrever métodos facilmente.

Leia mais sobre ele no livro do Addy Osmani.

Um exemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Define o objeto global do projeto, igual a um já existente ou cria um novo objeto.
var projeto = projeto || {};

// Define o módulo no objeto global.
projeto.moduloUm = (function() {
  'use strict';

  function iniciar() {
    interno();
    // ...
  }

  function atualizar() {
    // ...
  }

  function interno() {
    // ...
  }

  return {
    iniciar:iniciar,
    atualizar: atualizar
  };

}());

Módulos

Todos os scripts do Locaweb Style são modularizados ao máximo. Só iniciamos um comportamento se ele precisar ser usado. Todos os módulos ou os triggers destes módulos, terão um atributo data-ls-module="#" que avisará o Locaweb Style para iniciar o módulo determinado. Para citar alguns exemplos: data-ls-module="modal", data-ls-module="collapse" e data-ls-module="tabs"

O ideal é ter um módulo por arquivo, e que eles não se iniciem sozinhos.

Um módulo central que funcione como controlador de quais serão executados é uma boa prática.

Abaixo, colocamos três exemplos de módulos e como eles são carregados:

Módulo de gráficos no arquivo charts.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var projeto = projeto || {};
projeto.Grafico = (function() {
  'use strict';

  function iniciar() {
    inserirGrafico();
  }

  function inserirGrafico() {
    // ...
  }

  return {
    iniciar:iniciar
  };

}());

Módulo servidores no arquivo servers.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var projeto = projeto || {};
projeto.Servidores = (function() {
  'use strict';

  function iniciar() {
    buscaServidores();
  }

  function buscaServidores() {
    insereListaServidores()
    // ...
  }

  return {
    iniciar:iniciar
  };

}());

carregaModulos.js

Finalmente o arquivo que controla quando cada módulo será executado, da maneira que preferir

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var projeto = projeto || {};
projeto.carregaModulos = (function($) {
  'use strict';

  function inicio() {
    if ( $('.grafico').size() ) {
      projeto.graficos.inicio();
    }

    if ( window.location.pathname === '/servidores' ) {
      projeto.servidores.inicio();
    }
  }

  return {
    inicio:inicio
  };

}(jQuery));

projeto.carregaModulos.inicio();

Código em apenas um idioma

Para facilitar a manutençao e a legibilidade do código, procure usar apenas um idioma, em nomes de funções, variáveis e comentários.

O mais importante é seguir um padrão, mantendo ele do início ao fim do projeto. Exceções, claro, são libraries e plugins que utilizados.

Seja qual for a língua utilizada é importante ser claro, utilizando nomes descritivos, evitando ser prolixo nos nomes, funções e comentários, como abordado no tópico Seja compreensível abaixo.

'use strict';

Ao utilizar "use strict"; no início de códigos ou funções, declara-se uma mudança na sintaxe do Javascript, que lança mais exceções mostrando problemas no código. Os erros mais comuns são uso de palavras reservadas do javascript (ECMAScript 5 e 6), uso de variáveis não declaradas e uso de funções descontinuadas.

Para utilizar, basta inserir a string 'use strict'; antes do bloco de código a ser avaliado ou função. Exemplos:

1
2
3
4
5
6
7
"use strict";
idade = 17; // lança um erro de referência

function soma(a, b, c) { // erro de sintaxe
  "use strict";
  return a + b + c; // exibe o erro se a função é chamada
}

Leia mais em MDN - Strict mode

Nomenclatura de pastas, arquivos, módulos e plugins

Um projeto pode ter muitos arquivos javascript, então é importante que estejam bem organizados desde o início, separados e bem nomeados.

A estrutura pode variar muito de projeto para projeto, mas as recomendações mínimas são:

  • Nomes dos arquivos na mesma língua em que são escritos;
  • Nomes sem camelCase;
  • Pastas separadas por tipos (bibliotecas/frameworks/plugins);
  • Plugins identificados por versão.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
── javascripts
     ├── libs
        ├── jquery.min.js
        └── underscore.min.js
        └── highcharts.min.js
     ├── plugins
        ├── jquery.validate-1.2.js
        ├── jquery.slider-3.1.js
        └── jquery.validate.addicional-methods-0.8.js
     ├── modules
        ├── charts
        |   ├── servers.js
        |   └── transfer.js
        ├── servers.js
        └── servers.forms.js
     ├── utils.js
     └── main.js

Seja compreensível

Use nomes de variáveis e funções auto explicativos e simples. Crie algum padrão e mantenha em todo o projeto.

No Locastyle utilizamos variáveis e funções camelCase, pela facilidade de leitura, escrita e praticidade ao se trabalhar.

Exemplos:

Variáveis com nomes ruins:

1
2
3
4
5
6
7
8
// Curtos, posicionamento no código e abreviações
var x1;
var campo1;
var latXY;

// Longos demais
var valorEixoXGraficoConsumo;
var campoTextoPrimeiroNome;

Funções com nomes ruins:

1
2
3
4
5
6
7
8
// Nomes que descrevem o código, nao o objetivo da função
function maiorDeDezoitoAnos(idade){
  return idade >= 18;
}
// É melhor descrever o objetivo
function possuiMaioridade(idade){
  return idade >= 18;
}

É uma boa ideia criar um padrão para suas variáveis e funções, como por exemplo:

1
2
3
4
5
6
7
8
9
10
// Variáveis com $ no início são elementos/objetos jQuery
var $header    = $('#header');
var $menuItens = $('#menu a');

// Maiúsculas para constantes
var PASTA_IMAGENS = '/assets/images/';
var NOME_CLIENTE = 'Fulano de Tal';

// _ no início para variáveis e funções privadas
var _contador = 0;

Confira o padrão de nomenclatura do Douglas Crockford

Evite globais

No geral é uma péssima idéia, porque aumenta a chance de ter algo sobrescrito. Uma opção é utilizar closures e module pattern.

Seja consistente no estilo de código

É possível escrever seu código de muitas maneiras, mas procure manter o mesmo estilo em todo seu projeto. Mantendo um padrão nos nomes, identacões, patterns, etc.

Uma dica, utilize o jslint para validar seu código.

Escreva os comentários necessários

É comum ouvir "Um bom código não precisa de explicação", mas na prática em projetos maiores, procure explicar a finalidade do seu código. Muitas pessoas, de diferentes níveis, podem ter que trabalhar no seu código e nem sempre elas tem experiência, tempo ou conhecimento do negócio para entender tudo. Facilite o desenvolvimento e manutenção comentando, mas não explicando o que ele faz, mas qual a regra de negócio.

Exemplo:

1
2
3
// Ruim: verifica se é maior de 18
// Bom: menores de idade são redirecionados
if( idade >= 18 ){ ... }

Lembrando que comentários devem existir apenas na versão de desenvolvimento, devendo ser removidos no arquivo minificado que é entregue em produção.

Use testes automatizados

Utilizamos Jasmine para testar o Locaweb Style, assim como os comentários, é uma ótima forma de explicar o que seu código faz ou deveria fazer. Além de ter o dispositivo de alerta quando algum teste quebra, dá mais segurança para manutenções e inclusão de novas funcionalidades.

Evite misturar tecnologias

Na prática do dia a dia, algo bem simples: estilize seu HTML com CSS, não com JS.

1
2
3
4
5
6
7
// Errado
$('#nome-usuario').css({
  'border': '1px solid red',
  'color': 'red'
});
// Certo
$('#nome-usuario').addClass('erro');

Crie os estilos que precisar (e animações, quando possível) no CSS, e no javascript controle quando os estilos são aplicados, em vez de aplicar propriedades.

Outro ponto importante é seguir a jQuery. Eu sei que você vai querer escrever JavaScript puro em alguns momentos. Mas isso complica a leitura do código e sai totalmente do padrão inicial definido que é usar a abstração da jQuery. Por isso, use sempre os comandos da jQuery.

Use sintaxe abreviada

Conheça as notações de variáveis e funções abreviadas e procure usá-las.

Exemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// Use
var cores = ['rosa', 'azul', 'verde'];

// Em vez de
var cores = new Array();
cores[0]='rosa';
cores[1]='azul';
cores[2]='verde';

// Use
var margem = altura || 10;

// Em vez de
if(altura === undefined){
  var margem = altura;
} else {
  var margem = 10;
}

// Use
var direcao = (x > 100) ? 1 : -1;

// Em vez de
var direcao;
if(x > 100){
  direcao = 1;
} else {
  direcao = -1;
}

Modularize seu código

Evite escrever funções, trechos de código muito longos, ou aninhados. Procure separar regras e evite códigos repetidos.

Exemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// Em vez de
$('#botao1').on('click', function(){
  $('#resultado').load('ajax/lista-pessoas.html', function() {
    $('#formulario').slideUp()
  });
})
$('#botao2').on('click', function(){
  $('#resultado').load('ajax/lista-empresas.html', function() {
    $('#formulario').slideUp()
  });
})
//...

// Faça
function ocultaFormulario(){
  $('#formulario').slideUp();
}
$('#botao1').on('click', function(){
  $('#resultado').load('ajax/lista-pessoas.html', function() {
    ocultaFormulario();
  });
})
$('#botao2').on('click', function(){
  $('#resultado').load('ajax/lista-empresas.html', function() {
    ocultaFormulario();
  });
})

// Ou melhor
function ocultaFormulario(){
  $('#formulario').slideUp();
}
function carregaDados( elemento, url){
  $(elemento).on('click', function(){
    $('#resultado').load(url, function() {
      ocultaFormulario();
    });
  })
}
carregaDados('#botao1', 'ajax/lista-pessoas.html');
carregaDados('#botao2', 'ajax/lista-empresas.html');

Evite muitos aninhamentos

Facilite o entendimento e manutençao dos seus códigos. Utilize as práticas anteriores e evite um código do tipo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$('#botao').on('click', function(){
  $.ajax({
    type: "POST",
    url: 'usuarios',
    success: function(data){
      $('resultado').fadeIn('fast', function(){
        $('#formulario').animate({
          heigth : 0,
          opacity: 0
        }, 300, function(){
            $('#mensagem').animate({
              heigth : 200,
              opacity: 1
            }, 300, function(){
              // ...
            })
          }
        )
      })
    },
    error: function(){
      $('#mensagem').text(mensageErro);
    }
  });
});

Otimize loops

Existem várias maneiras de fazer loops, uma melhores que outras. Hoje, comum encontrar códigos usando loops do jquery ($.each) onde loops nativos poderiam resolver. Uma técnica simples para melhorar ainda mais os loops for() nativos é fazer cache de variáveis de comparação, evitando executar o .length a cada iteração.

Exemplo:

1
2
3
4
5
6
7
8
9
10
11
// Use
var cores = ['Azul', 'verde', 'rosa', 'vermelho'];
for(var indice = 0, quantCores = cores.length; indice < quantCores; indice++){ //
  console.log( cores[indice] );
}

// em vez de
var cores = ['Azul', 'verde', 'rosa', 'vermelho'];
for(var indice = 0; indice < cores.length; indice++){
  console.log( cores[indice]) ;
}

Para comparação, um teste de performance no jsperf analisando diversos tipos de loop. O loop otimizado, como acima, executou 159k vezes, contra 113k vezes do tradicional.

Minimize acessos ao DOM

Evite ao máximo acessar o DOM para buscar ou inserir informações. É lento e não se pode confiar no que está no DOM. Coisas simples podem minimizar o acesso, por exemplo, se alguma função precisa atualizar uma tabela no seu HTML, em vez de percorrer por alterando os valores, pode ser mais eficiente criar uma função que reescreva toda a tabela, e depois simplesmente troque a antiga pela nova. Outra simples é fazer cache de objetos jQuery, por exemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Em vez de
$('#botaoEnviar').on( 'click', function(){
  $(this).prop( 'disabled', true );
  $('$formulario').addClass( 'enviando' );
  $.post( 'ajax/contato', function( dados ) {
    $('#mensagem').html( dados );
    $('$formulario').removeClass( 'enviando' );
    $('#botaoEnviar').prop( 'disabled', false );
  });
});

// Faça
var $botaoEnviar = $('#botaoEnviar');
var $formulario  = $('#formulario');
var $mensagem    = $('#mensagem');

$botaoEnviar.on( 'click', function(){
  $botaoEnviar.prop( 'disabled', true );
  $formulario.addClass( 'enviando' );
  $.post('ajax/contato', function( dados ) {
    $mensagem.html( dados );
    $formulario.removeClass( 'enviando' );
    $botaoEnviar.prop( 'disabled', false );
  });
});