Vaadin

Você já ouviu falar do Vaadin? Ainda não? É um framework muito legal. Ele usa o GWT para construir sua interface, mas trabalha de uma forma um pouco diferenciada. Quer saber mais detalhes? Então acesse o blog do JavaBahia que tem o primeiro artigo que lançarei por lá. É o primeiro, bem introdutório, mas já serve para apresentar um pouco a ideia.
É isso. Ah, claro. Faltou o link!

http://javabahia.blogspot.com/
http://javabahia.blogspot.com/2010/03/vaadin-parte-1.html

Abraços e espero que gostem.

Singletons em Javascript

Você já pensou em escrever uma classe considerando o padrão de projeto Singleton? Provavelmente você leu em algum lugar de que é impossível. Bem, não é bem assim. Talvez não haja uma maneira igual à da linguagem Java. Mas, de certa forma, é possível. Em um post anterior, eu comentei sobre uma nova forma de escrever classes em Javascript, e é usando esta forma que dá para escrever um Singleton. Veja este código:

Singleton = function() {

  // variáveis e método privados.

  var variavelprivada = 0;

  function funcaoprivada() {
  }

  // variáveis e métodos públicos.
  return {

    metodo: function() {
        alert("singleton");
    }

};
}();

Há uma pequena modificação com relação ao código do post anterior. Observe na última linha, logo após as chaves, os dois parênteses. O que aconteceu, então? Para entender melhor, é preciso compreender bem a linguagem Javascript. Já discuti em outros posts alguns destes detalhes. Inclusive, destaquei as diversas maneiras que você pode usar para escrever classes. Lembre-se que ao fazer algo do tipo f = function() {}, você já está, de certa forma, definindo uma classe. Você pode fazer, var objeto = new f(); e terá uma instância da classe f.

Com relação ao exemplo que escrevi, em um primeiro momento, você definiu uma classe com métodos privados e públicos. Quando você colocou os dois parênteses no final, você executou a função, fazendo que ela retornasse um Array de métodos (que define sua classe). Porque isto é um Singleton? Você não pode fazer new Singleton, porque, de fato, você não definiu uma classe que poderia ser instanciada. Para chamar os métodos, basta fazer Singleton.metodo(). Neste caso, você tem uma única instância da sua classe, satisfazendo ao que solicita o padrão de projeto.

Javascript: Orientação a Objetos – Herança

A programação orientada a objetos possui diversas vantagens, as quais não pretendo entrar em detalhes. Em Javascript existe a possibilidade de se programar orientado a objetos, embora este estilo de programação nesta linguagem seja um pouco diferente, e acabe causando espanto nos iniciantes. Principalmente para quem é acostumado com linguagens como Java, o estilo de código orientado a objetos em Javascript é muitíssimo diferente.

Mas não apenas o estilo, também o comportamento! O que dizer da herança? A herança em Javascript, não é como você está acostumado a ver nas linguagens tradicionais. O que existe, então? O que costuma-se chamar de herança estática, ou seja, uma nova classe filha literalmente copia todos os atributos e métodos da classe pai. Isto trás diversas conseqüências que você tem que ficar bastante atento, pois senão seu código vai se comportar de maneira inesperada.

“Ei, você fala em herança estática, mas como eu faço isso? Cadê o ‘extends’ ?”. Pois é, não existe. Para você aplicar a herança, é necessário um pouco de código, pois não existe uma palavra chave, como extends, que ajude você. Também é necessário entender o significado de “Prototype”. Para isto, vamos lembrar do padrão de projeto Prototype, pois a idéia é semelhante, senão a mesma. Segundo nosso colega José Anízio Pantoja Maia, em seu artigo publicado no GUJ:”O Pattern Prototype tem como objetivo criar objetos específicos a partir da instância de um protótipo. Isso permite criar novos objetos através da cópia deste protótipo.”.

Ele também nos dá um exemplo que ilustra bem a idéia do padrão: “O uso de células representa perfeitamente os objetivos deste pattern. Uma célula dividia em duas se tornam duas células idênticas com as mesmas funcionalidades.”. Então, em Javascript toda classe possui um Protótipo, que representa um “template” das funcionalidades que esta classe possui. Desta forma, você pode criar uma nova classe herdando” o protótipo de outra.

Vamos a um exemplo de uma classe em javascript, criada sem ajuda de bibliotecas:

// Construtor.
function MinhaClasse() {
this.umatributo = "Atributo de MinhaClasse";
}

// Definindo o prototype.
MinhaClasse.prototype = {
umMetodo: function() {
alert("Um Atributo de MinhaClasse: " + this.umatributo);
},

outroMetodo: function() {
}
}

//Instanciando a classe e testando.
var minhaClasse = new MinhaClasse();
minhaClasse.umMetodo();

Reparou alguma semelhança com os “arrays associativos” que comentei em posts anteriores? Pois é, uma classe parece um Array Associativo contendo funções e variáveis, não? E mais uma coisa, esta forma de criar uma classe em Javascript não é a única. Você também poderia fazer:

var MinhaClasse = function() {

// Definindo o construtor.
this.umatributo = "Um Atributo";
};

// Definindo um novo método no prototype.
MihaClasse.prototype.meuMetodo = function() {
alert(this.umatributo);
};

// Instanciando.
var minhaClasse = new MinhaClasse();
minhaClasse.meuMetodo();

E que tal esta?

function MinhaClasse() {
this.umatributo = "Um Atributo";
}

var instancia = new MinhaClasse();
instancia.meuMetodo = function() {
alert(this.umatributo);
}
instancia.meuMetodo();

Opa, existe ainda outra forma:

function MinhaClasse() {
this.umatributo = "Um Atributo";

// Definindo o método umMetodo como sendo a função _umMetodo.
this.umMetodo = _umMetodo;

// Uma função que vai representar o método.
function _umMetodo() {
alert(this.umatributo);
}

}
var instancia = new MinhaClasse();
instancia.umMetodo();

Confuso, não? Eu também acho, e demorei até me acostumar. Sugiro adotar a maneira que mais lhe agrada e sempre usar ela. Eu prefiro a primeira forma, pois agrupa melhor o que pertence a uma classe. Assim sendo, adotarei este estilo daqui em diante. Voltemos ao assunto da herança e o tal do Prototype. Você está atento e observou no primeiro exemplo a passagem …MinhaClasse.prototype = { … }… Pois é, estou definindo o protótipo. E caso eu queira criar uma nova classe e herdar desta MinhaClasse? Vamos lá:

// Construtor.
function MinhaClasse() {
this.umatributo = "Atributo de MinhaClasse";
}

// Definindo os métodos.
MinhaClasse.prototype = {

// Método 1.
umMetodo: function() {
alert("Um Atributo de MinhaClasse: " + this.umatributo);
},

// Método 2.
outroMetodo: function() {
}

}

function MinhaClasseFilha() {
this.umnovoatributo = "novo atributo";
}

MinhaClasseFilha.prototype = new MinhaClasse();
var minhaClasseFilha = new MinhaClasseFilha();
minhaClasseFilha.umMetodo();

Agora você possui o método “umMetodo” na sua classe filha. Agora um grande detalhe, que você deve prestar atenção! Quando você define um método no “protótipo” da classe, todas as instâncias desta definição de classe irão possuir este método! A herança só é possível com protótipos, portanto, cuidado com códigos como este:

// Construtor.
function MinhaClasse() {
this.umatributo = "Atributo de MinhaClasse";
}

MinhaClasse.prototype = {
umMetodo: function() {
alert("Um Atributo de MinhaClasse: " + this.umatributo);
},

outroMetodo: function() {
}

}

// Classe Filha.
function MinhaClasseFilha() {
this.umnovoatributo = "novo atributo";
}

// Herdando o prototype da classe Pai.
MinhaClasseFilha.prototype = new MinhaClasse();
MinhaClasseFilha.metodoTeste = function() {
alert("Método de Teste");
}

// Mais uma Classe.
function MinhaSegundaClasseFilha() {
}

MinhaSegundaClasseFilha.prototype = new MinhaClasseFilha();
var minhaSegundaClasseFilha = new MinhaSegundaClasseFilha();
// Ops, será que esse método existe? Não!
minhaSegundaClasseFilha.metodoTeste();

Percebeu a diferença sutil? O método metodoTeste não foi definido dentro do prototype da classe MinhaClasseFilha, portanto, a classe MinhaSegundaClasseFilha não vai possuir este método. Outro detalhe, não existe sobrecarga de métodos em Javascript, caso você reescreva o método na classe filha, o método da classe pai foi perdido.

Algumas bibliotecas auxiliam na criação de objetos, como a Prototype, que já comentei anteriormente. Em um próximo artigo, vou explicar melhor a utilização dela. E por último, alguém me ajuda a escolher um tema definitivo para o blog! Eta indecisão! 🙂

Javascript: Contexto das Funções

Observei alguns erros comuns ao utilizar funções, ou métodos, como parâmetros para outras funções. Como assim? Vislumbre o código abaixo:

function testando() {
   alert("teste");
}

function outroTestando(f) {
   f();
}

outroTestando(testando);

Sim, caso você não saiba, em Javascript isto é possível. Será apresentado um alerta com a palavra “teste” na tela. Mas o que isto tem a ver com o título deste post? Agora imagine que você tem um objeto(a classe abaixo está definida usando a biblioteca Prototype:

var MinhaClasse = Class.create(); // Class.create é da Prototype.
MinhaClasse.prototype = {
initialize: function() {
// construtor.
// definindo um atributo para esta classe.
    this.umatributo = "testando";
},

  // Um método da minha classe.
  meuMetodo: function() {
    alert(this.umatributo);
  }
}

// Uma função externa à classe.
function funcaoTeste(f) {
f();
}

// Instanciando um objeto do tipo MinhaClasse.
var minhaClasse = new MinhaClasse();
funcaoTeste(minhaClasse.meuMetodo);

O que o alerta vai imprimir? Vazio, nada, undefined, null… Porque? O atributo definido por “this.umatributo” perdeu o contexto no qual estava, que era o da classe MinhaClasse. Agora este atributo está no contexto da função “funcaoTeste” e esta função não possui um atributo com este nome. Entendeu? Mas porque eu falo isso? Porque você faz códigos como este muito em Ajax, quando você passa a função de “callback”, lembra? Portanto, tome cuidado quando for passar como função de callback um método de uma classe sua, pois todos os atributos referenciados com “this” podem não ter os valores que você esperava.

Agora mais uma, pra ficar mais claro, e para você entender melhor como esta linguagem é bastante dinâmica e interessante:

var MinhaClasse = Class.create(); // Class.create é da Prototype.

MinhaClasse.prototype = {

initialize: function() {
// construtor.
// definindo um atributo para esta classe.
this.umatributo = "testando";
},

// Um método da minha classe.
meuMetodo: function() {
alert(this.umatributo);
}

}

var MinhaOutraClasse = Class.create();
MinhaOutraClasse.prototype = {

initialize: function() {
// construtor.
// definindo um atributo para esta classe.
this.umatributo = "testando na nova classe.";
}
}
var minhaClasse = new MinhaClasse();
var minhaOutraClasse = new MinhaOutraClasse();

minhaOutraClasse.meuMetodo = minhaClasse.meuMetodo;
minhaOutraClasse.meuMetodo();

Isso mesmo, vai ser impresso “testando na nova classe”. 🙂

Javascript: Prototype e suas Funcionalidades

Sempre adotei a biblioteca Prototype em meus projetos. Embora existam outras bibliotecas que fornecem funcionalidades semelhantes, continuo adepto da Prototype. Pode ser por mera preguiça de procurar algo novo, como também pela acomodação, pois tudo que preciso a Prototype faz.

Entre as funcionalidades que mais me agradam, a classe Form merece destaque. Como você faria para iterar por todos objetos de um formulário? Normalmente vejo códigos como este:

var elementos = documento.getElementById("idDoForm").elements;
for ( var indice = 0 ; indice < elementos.length; indice++ ) {
  var elemento = elementos[indice];
  // Fazer algo aqui.
}

A prototype torna este trabalho mais fácil:

Form.getElements("idDoForm").each( function(elemento) {
  // Fazer algo aqui.
} );

Javascript: Closure

Em um determinado ponto do projeto no qual trabalho havia a necessidade de que a mesma função que fazia a chamada Ajax, fosse também a função de callback. Isto é fácil, eu sei. Mas havia mais um problema: essa função na verdade era um método de uma classe, e eu precisava obter os dados de todo o objeto para trabalhar no callback.

Como assim? Vou apresentar um exemplo, entretanto, está totalmente direcionado ao DWR, um framework Java para trabalhar com Ajax. Em DWR você tem uma “classe” Javascript que reflete exatamente os métodos de uma classe Java. Portanto, em Javascript você poderia fazer algo do tipo:

MinhaClasse.meuMetodo("dadosParaEnviar", funcaoCallback);

No meu caso, o parâmetro funcaoCallback era um método de uma classe. Veja este trecho de código:

// Classe criada com Prototype.var m = Class.create();
m.prototype = {   // Construtor.
   initialize: function(){
      this.atributoQualquer = 10;
   },// Método Callback.

   callback: function(data) {
      alert(this.atributoQualquer);
   },

// Chamada Ajax.
   chamarAjax: function() {
      MinhaClasse.meuMetodo("dadosParaEnviar", this.callback);
   }
}

O que será impresso no alert quando houver o retorno da chamada Ajax? O número 10? Errado, pois seu método agora está fora do contexto do seu objeto. Vai ser impresso NULL ou UNDEFINED ou nada mesmo.

Como resolver? Eu usei closures em Javascript. Este mesmo código ficaria desta forma:

// Criar uma variável $this com referência ao próprio objeto.var
$this = this ;// Criar a closure.

// Está será a função a ser chamada no callback.
var callbackProxy = function(dataFromServer) {

// Quando ocorrer o retorno do Ajax no servidor,
// então chama o método preencherCombo.
$this.preencherCombo(dataFromServer);
} ;

// Metadados.
var callMetaData = { callback: callbackProxy } ;

MinhaClasse.meuMetodo("dadosParaEnviar", callMetaData);

Bom, é isso. Ficou confuso? Sugiro uma leitura deste texto.

Javascript: Arrays e Objetos

Sempre tive o costume de utilizar códigos semelhantes a este:

var colecao = new Array();

colecao["teste"] = new UmaClasseQualquer();

Apesar de pouco aparente, esta forma de programar não é a mais indicada. Arrays, em Javascript, devem ser usados preferencialmente com índices numéricos. Mas e se você quiser um array associativo igual ao do código apresentado? Use OBJETOS! Arrays associativos são objetos com atributos definidos dinamicamente.
Confuso? É, eu também acho. Mas há diversos inconvenientes em usar Arrays como associativos. Por exemplo:

var colecao = new Array();
colecao["length"] = 200;
colecao[0] = "teste";
colecao[1] = "teste2";
alert(colecao.length);

O que será apresentado no código acima? O número 3? Errado, será o número 200, pois você acabou de redefinir o método length existente nos objetos Array em Javascript.

O melhor seria, então:

var colecao = new Object();
colecao["length"] = 200;
foreach ( key in colecao ) {
   alert(key + "=" + colecao[key]);
}

Ah sim, e mais um detalhe. Caso você tenha criado um “array associativo”, não pense que length irá retornar o tamanho do array, pois, como eu já disse, não existem array associativos na verdadeira concepção da palavra, e sim objetos. Portanto:

var arr = {id:1, descricao:"teste"};
alert(arr.length);

Este código não vai lançar um alerta com o número 2. Primeiro, porque a variável arr não é um array para ter o método length. Segundo, porque arr é um objeto com dois atributos: id e descricao. Portanto, cuidado com códigos como este:

var arr = new Array();
arr[0] = "teste";
arr["teste"] = 2;
alert(arr.length);

O que será retornado? Caso tenha prestado atenção a tudo que eu disse, você dirá 1. 🙂