Herberth Amaral

Software development adventures

O que fazer quando seu codigo JavaScript se torna um monstro

without comments

Quando eu não conhecia jQuery e seus plugins, JavaScript era um tédio pra mim. É fato que uma biblioteca de alto nível (não só o jQuery, mas o mootools e o prototype, por exemplo) facilitam e deixam o desenvolvimento em JavaScript rápido e divertido, pois você não terá que se preocupar (muito) com detalhes de implementação de browsers.

Mas o que acontece quando, mesmo usando com alguma lib fodástica, seu código começa a ficar grande demais, complexo demais, fragmentado demais ou desorganizado demais? Isso é a minha definição de código monstro. Eis algumas dicas que podem te ajudar se você estiver passando por isso:

1 – Evite o Callback Hell

O jQuery mostra muitos exemplos usando funções anônimas como callback. De certo modo, isso é uma boa prática para situações simples, como o  tratamento do evento clique de um botão:

$("#meuBotao").click(function(){
  alert('Fui clicado!');
});

Mas nem sempre isso é legal: muitas vezes você quer reaproveitar essa função para outros callbacks, como por exemplo:

$('#meuBotao').click(getClientes);
$('#meuInput').blur(getClientes);

getClientes = function()
{
   $.get('/clientes/get','',
   function(data){
      //trata os dados recebidos aqui
   },'json')
}

Nesse caso, eu estou aproveitando minha função de callback getClientes para dois event listeners. Isso é bem legal, mas quando nosso código começa a crescer, nos esbarramos em outro problema: as funções globais.

2 – Evite funções globais

Isso quer dizer, ao invés disso:

$('#meuBotao').click(getClientes);
$('#meuInput').blur(getClientes);

getClientes = function()
{
   $.get('/clientes/get','',
   function(data){
      //trata os dados recebidos aqui
   },'json');
};

Faça algo assim:

$('#meuBotao').click(getClientes);

$('#meuInput').blur(Clientes.getClientes);

var Clientes = {
    getClientes:function()
    {
       $.get('/clientes/get','',
       function(data){
          //trata os dados recebidos aqui
       },'json');
    }
};

Isto é, coloque suas funções dentro de objetos. Assim você evita funções globais e evita fazer código “estruturado”, passando a usar os recursos da orientação à objetos do JavaScript e deixando o mínimo de globals possível. Essa é a forma mais fácil que eu conheço de se evitar funções globais e organizar melhor seu código, mas há outras formas como o Module Pattern.

3 – O “this” aponta para diferentes lugares em diferentes contextos. Saiba como lidar com isso.

Você não está deixando mais todas as suas funções como globais, está encapsulando tudo dentro de objetos, reaproveitando código e feliz da vida quando percebe que o this não é mais this. Calma que eu explico.

Você já deve ter visto algo assim no jQuery:

$('a').click(function(){
   $(this).html('fui clicado') ;
});

Isso faz com que, quando um link é clicado, o mesmo fique com o texto “fui clicado”. Deu pra notar que nesse caso, o this aponta para o elemento que disparou o evento. Mas olhe o seguinte exemplo:

var Cliente =
{
    texto:'Fui clicado',
    init:function()
    {
        //this aponta para o objeto Cliente
        $('a').click(this.aClickHandler);
    },
    aClickHandler:function()
    {
        //this aponta para o elemento "a" que disparou o evento
        $(this).html(Cliente.texto);
    }
};

Viu como “this” pode mudar de contexto? No exemplo acima, o problema de não ter o this apontando para o objeto Cliente foi facilmente contornado, mas você poderá precisar acessar o objeto pai de uma forma parecida com a this. Nesse caso, você pode passar um parâmetro para o evento usando o método bind() do jQuery, informando o contexto que ele foi chamado:

var Cliente =
{
    texto:'Fui clicado',
    init:function()
    {
        //this aponta para o objeto Cliente
        $('a').bind('click',{'self':this},this.aClickHandler);
    },
    aClickHandler:function(event)
    {
        var self = event.data.self;
        //o self aponta para Cliente e o this aponta para
        //o elemento "a" que disparou o evento
        $(this).html(self.texto);
    }
};

4 – Procure pelos patterns corretos.

Quem disse que padrões de projeto criam um vocabulário em comum na equipe não poderia ter dito algo mais pertinente:  o uso de padrões faz com que o desenvolvedor foque nas funcionalidades da aplicação sem se preocupar com alguns detalhes de implementação.

O AjaxPatterns contém uma coleção bem legal e bem documentadas de patterns para Ajax e JavaScript em geral. Mas não espere ter problemas pra consultar os patterns: quanto mais se conhece sobre padrões, mais fácil é pensar em soluções de problemas e planejamento em geral.

5 – Deixe apenas um $(document).ready em todo o seu código

Eu diria isso para todos os event listeners que você possa vir a colocar, mas o $(document).ready é o mais crítico na minha opinião. No JavaScript não há sobreposição de eventos: se você colocar dos event listeners para um mesmo evento, os dois serão executados. Isso pode dar problemas, pois você pode deixar o $(docuement).ready em dois arquivos diferentes e você pode desejar que um evento execute antes de outro.

6 – Valide seu JavaScript

Browsers interpretam JavaScript de forma diferente, então é sempre bom ter uma padronização de código para que não tenhamos problemas com sintaxe em diferentes browsers. Uma ferramenta de validação bem legal é o jslint.

– EDIT–

Nem sei onde tava com a cabeça quando esqueci isso:

7 – Escreva testes!

Testes pode ser tido como documentação executável e facilita muito quando você pega um código de outro desenvolvedor que já tenha testes: é fácil de ver os modos de uso do código e você se sentirá seguro ao fazer algo e ver que os testes passam. Além do mais, você não precisa encher seu código de comentário pra explicar como ele funciona (comentar é bom, mas sem exageros);

Entretanto, testar JavaScript pode não ser tão fácil assim. É necessário mais disciplina e paciência do que é necessário para testar seu código backend, mas é algo que se adquire com o tempo.

See ya!

Posts relacionados:

  1. Como voce testa seu JavaScript?

Written by Herberth Amaral

March 11th, 2010 at 10:08 pm

Leave a Reply