Metas nerds para 2013

Aproveitando o final do ano – e a vontade de voltar a postar – para desenterrar essa seção anual do blog =)

Profissionalmente falando, esse ano foi o mais diferente de todos os que eu vivi. No final do ano passado consegui cumprir meu objetivo de trabalhar na ThoughtWorks, e no último dia 12 completei um ano aqui. Foi um ano muito agitado. Trabalhei com muita coisa nova, e conheci pessoas maravilhosas e lugares interessantíssimos. Acima de tudo, aprendi muita coisa, com meus acertos e meus erros também.

Agora sinto que é hora de traçar um novo objetivo profissional. Sempre gostei muito de jogos, e desde que comecei a programar sempre tive vontade de um dia trabalhar com desenvolvimento de jogos. Então esse ano vou empregar meus esforços de estudo nessa direção.

Até que já fiz alguns joguinhos, mas nada com muito compromisso. Agora é hora de levar esse objetivo a sério. Estava então pensando em qual plataforma eu poderia investir, e a conclusão que eu cheguei é que eu posso começar desenvolvendo joguinhos para o elemento canvas do HTML5. Então é por aí que vou começar.

Dito isto, traço agora os passos que pretendo seguir durante o ano:

  • Aprender (bem) Javascript e tecnologias relacionadas, como Node.js;
  • Desenvolver um pequeno jogo para pôr os conhecimentos em prática. A idéia já está bolada, não vai ser nada novo, apenas a recriação de um jogo que já vi antes. Quando criar o repositório no Github postarei aqui;
  • Dar continuidade ao projeto que já iniciei, que envolve a criação de um portal onde as pessoas podem conversar e jogar os jogos que eu pretendo desenvolver durante o ano;
  • Se der tempo, e dependendo da minha determinação, quero criar um pequeno FPS, nada muito complexo.

Paralelamente a isso, pretendo contribuir com material para o portal Esfera Geek. Fui convidado pelo meu amigo Marcus para contribuir com artigos e reviews, e até já participei de algumas coisas por lá.

Feliz 2013 a todos nós, e que consigamos cumprir todos os nossos objetivos!

Anúncios
Metas nerds para 2013

Café Ágil + Super Sunday ThoughtWorks em Natal

A ThoughtWorks é uma empresa de consultoria em desenvolvimento ágil com escritórios em vários países do mundo, e recentemente vem expandindo suas atividades pelo Brasil. O primeiro escritório foi montado em Porto Alegre/RS e o segundo foi aberto no meio deste ano em Recife/PE.

Nos próximos dias 10 e 11 de novembro a ThoughtWorks promoverá um evento em Natal/RN. No sábado (dia 10) pela manhã vai rolar um Café Ágil, com palestras diversas da galera que trabalha por lá sobre agilidade, tecnologia e temas afins. Pela tarde teremos um dojo usando a linguagem Scala.

O dia 11 será dedicado a você que quer participar dessa revolução no mundo de TI que a ThoughtWorks proporciona. Uma série de entrevistas será realizada com o pessoal que se interessar em trabalhar conosco. Se você mora em Natal ou nas regiões vizinhas, não deixe de se juntar a nós! Essa é sua chance!

Para mais detalhes, visite o site do evento para conferir locais, palestras e preencher o formulário de inscrição. Nos vemos lá!

Café Ágil + Super Sunday ThoughtWorks em Natal

Reborn

Se houvesse um ranking na internet de tempo de abandono de blogs, eu estaria nas primeiras posições com certeza. O último post que eu escrevi foi em 2009, e deixei inclusive artigos inacabados. Três anos depois volto aqui na melhor das intenções de readquirir o hábito de reescrever.

Espero desta vez voltar definitivamente à ativa. Vou procurar escrever sobre outras coisas que gosto, não somente programação. Mas realmente preciso acabar de escrever aquele artigo de proxies dinâmicos que comecei – e vai ser até um pouco estranho, pois não tenho mais trabalhado com Java ultimamente.

É, muita coisa tem acontecido… Mudei de trabalho, de cidade, de objetivos até. Tenho expandido meu círculo social a ponto de ter que me preocupar em postar coisas em inglês também. Vai ser uma experiência interessante.

Reborn

Usando um Map<String, Object> para armazenar os parâmetros de um Managed Bean

Antes de escrever a segunda parte do artigo, vou apresentar o código do managed bean mencionado na seção de comentários do post anterior.

Na ocasião, o leitor Alessandro questionou os motivos de passar para os métodos create() e update() dos services um Map<String, Object> contendo os dados a serem persistidos ao invés da própria entidade. Respondi então que um desses motivos era a existência de um managed bean cujos atributos mapeados para a página JSF correspondente estavam contidos em um Map<String, Object> – onde a key é o nome do atributo e o value, seu valor – e assim seria mais fácil passá-lo para os services.

Sem mais delongas, segue o código (comentários javadoc removidos para torná-lo mais sucinto).

public abstract class ManagedBean {
	private Map<String, Object> parametros = new HashMap<String, Object>();
	
	protected final void definirParametros(String... nomesParametros) {
		for (String nome: nomesParametros) {
			parametros.put(nome, null);
		}
	}
	
	protected final void limparParametros() {
		for (String parametro: parametros.keySet()) {
			parametros.put(parametro, null);
		}
	}
	
	public final Map<String, Object> getParametros() {
		return parametros;
	}

	public final void setParametros(Map<String, Object> parametros) {
		this.parametros = parametros;
	}

	// Outros métodos omitidos.
}

Como usá-lo? Suponha que estamos construindo um managed bean responsável pelas operações de login do usuário (que contém os campos nome e senha). Ele pode ser implementado escrevendo-se o código abaixo:

public class LoginBean extends ManagedBean {
	public LoginBean() {
		// Definindo dois campos para a página de login.
		super.definirParametros("login", "senha");
	}

	public String efetuarLogin() {
		// A classe ApplicationServiceFactory foi apresentada no post anterior.
		Usuario usuario = ApplicationServiceFactory
			// Obtendo o service de usuário, que realizará o login.
			.getUsuarioService()
			// Passando diretamente o Map contendo os campos.
			.efetuarLogin(super.getParametros());

		// Restante do código omitido.
	}
}

Na página JSF correspondente a esse managed bean teríamos controles referenciando os parâmetros da seguinte forma:

<h:inputText value="#{loginBean.parametros['login']}" />
<h:inputText value="#{loginBean.parametros['senha']}" />

O ganho com essa abordagem aparece principalmente quando uma página possui muitos campos. Assim não precisa ficar replicando os atributos da entidade no managed bean, e nem mesmo usar a própria entidade - e se ver obrigado a usar getters e setters que expõem aqueles atributos que não seriam interessante expor. Sem contar que essa forma abre espaço para usar reflection para automatizar a passagem dos valores dos atributos para a entidade correspondente.

Quaisquer sugestões ou dúvidas podem ser apresentadas na seção de comentários.

Até lá!

Usando um Map<String, Object> para armazenar os parâmetros de um Managed Bean

Services, transações e proxies dinâmicos – parte I

Introdução

No primeiro semestre deste ano cursei uma disciplina na faculdade onde o trabalho final consistia em escrever um software usando apenas Hibernate e JSF. Desenvolvi então um software de gestão de transporte de cargas, que poderia ser comercializado para empresas que fazem uso de uma frota de veículos para realizar transportes rodoviários.

Falando um pouco sobre sua arquitetura, ele dispõe de uma camada de aplicação composta de serviços que são requisitados pela camada de apresentação – nesse caso, pelos managed beans. O código cliente conhece apenas a interface desse serviço, expressa no código abaixo:

interface EntityService<T, ID extends Serializable> {
    void create(Map<String, Object> parameters);
    Collection<T> readAll();
    T read(ID id);
    Collection<T> readByParameters(Map<String, Object> parameters);
    void update(Map<String, Object> parameters);
    void delete(T t);
}

Cada serviço da camada deve ser expresso através de uma interface que estenda EntityService. Por exemplo, o código abaixo corresponde ao serviço de cadastro de veículos.

public interface VeiculoService extends EntityService<Veiculo, String> {
    // Declaram-se aqui outras operações requeridas por esse serviço.
}

A implementação desse serviço deve conter o corpo para todos os métodos declarados nas duas interfaces. Note que a mesma não precisa ser pública.

class VeiculoServiceImpl implements VeiculoService {
    // Fornece implementações para todos os métodos.
}

Há desvantagens nessa abordagem. Nem sempre é conveniente disponibilizar todos os serviços declarados em EntityService para uma determinada entidade. Por exemplo, e se algum requisito do projeto exigisse que não fosse possível alterar veículos? O código abaixo ilustra uma solução possível.

class VeiculoServiceImpl implements VeiculoService {
    // Não é possível alterar veículos.
    public void update(Map<String, Object> parameters) {
        throw new UnsupportedOperationException("Operação não permitida.");
    }
}

Porém, a discussão do que seria melhor ou não não está no escopo desse artigo, embora fosse interessante continuá-la na seção de comentários.

Finalmente, a classe abaixo é usada pela camada de apresentação para requisitar os serviços.

public class ApplicationServiceFactory {
    public static VeiculoService getVeiculoService() {
        return new VeiculoServiceImpl();
    }
}

Contexto transacional

A abordagem acima é interessante, mas as operações de cada serviço não são executadas sob contexto transacional. Isto é, se tivermos uma operação que precise realizar duas ou mais instruções de persistência de dados, uma eventual falha ocorrida em uma dessas instruções não cancela as anteriores. Isso pode acarretar em estado inconsistente dos dados. Precisamos então aplicar uma solução que permita que as operações dos serviços executem sob contexto transacional.

Há várias soluções para o problema:

  • Usar Spring;
  • Escrever um aspecto;
  • Usar o padrão Proxy.

O objetivo deste artigo é explorar o padrão Proxy e a API de proxies dinâmicos do Java para aplicar um contexto transacional para todos os serviços da aplicação. Será o que desenvolveremos na parte 2.

Até lá!

Services, transações e proxies dinâmicos – parte I

Passagem explícita de tipos para métodos genéricos em Java

Quando temos uma classe genérica em Java, precisamos sempre passar de forma explícita o tipo do parâmetro genérico. O uso da classe ArrayList<E> exemplifica isto.

List<Usuario> l = new ArrayList<Usuario>();

Aqui estamos indicando explicitamente que a nossa lista contém apenas instâncias da classe Usuario.

Problema

Quando criamos métodos genéricos, geralmente declaramos argumentos na assinatura do método que permitem ao compilador inferir o tipo genérico, sem que precisemos indicar de forma explícita. Como exemplo, temos o método Collections.copy() da API do Java que copia elementos de uma collection para outra. A declaração do método é:

public static <T> void copy(List<? super T> dest, List<? extends T> src) {
    // Copia os elementos de src para dest,
}

Se usarmos o método da seguinte forma:

List<Usuario> lista1 = new ArrayList<Usuario>();
List<Usuario> lista2 = new ArrayList<Usuario>();
Collections.copy(lista1, lista2);

Damos condições para que o compilador deduza, a partir do tipo dos argumentos dest e src, que T representa instâncias da classe Usuario. Mas há situações em que isso não é possível, como no método abaixo:

public class FabricaDeListas {
    public static <T> List<T> criarNovaListaDeQualquerCoisa() {
        return new ArrayList<T>();
    }
}

Aqui o compilador não dispõe de argumentos no método para tentar inferir o tipo T. Precisamos passar de forma explícita, assim como fazemos com classes. Mas como fazer isso?

Solução

A página 86 do livro Java Precisely (2ª edição, 2005), na seção 21.8 – Generic Methods, indica a sintaxe da linguagem para resolver o problema:

Classe.<Tipo1, Tipo2, ..., TipoN>metodoEstatico(); // Para métodos estáticos
instancia.<Tipo1, Tipo2, ..., TipoN>metodo(); // Para métodos de instância.

Ou seja, tomando o exemplo anterior, podemos escrever:

List<Usuario> = FabicaDeListas.<Usuario>criarNovaListaDeQualquerCoisa();
List<Cachorro> = FabicaDeListas.<Cachorro>criarNovaListaDeQualquerCoisa();

E assim sucessivamente. Notem que é preciso indicar de forma explícita a entidade que invoca o método, seja uma classe ou um objeto.

Passagem explícita de tipos para métodos genéricos em Java

Configurando ambiente JRuby on Rails + SQLite3 no Windows

JRuby é uma implementação da linguagem Ruby escrita 100% em Java que oferece total suporte a Ruby on Rails. O objetivo deste tutorial é configurar um ambiente de desenvolvimento Ruby on Rails no Windows utilizando JRuby e o banco de dados SQLite3. Apesar de ter sido escrito especificamente para Windows, ele pode ser facilmente adaptado para outras plataformas.

No momento da publicação deste tutorial as versões das tecnologias envolvidas eram:

  • Java – JDK 6 update 14
  • JRuby – 1.3.1
  • Ruby on Rails – 2.3.3
  • SQLite3 – 3.6.17

Vamos lá:

Passo 1 – baixe o JDK diretamente do site da Sun e instale-o conforme recomendado, criando a variável de ambiente JAVA_HOME que aponta para o diretório de instalação e adicionando o caminho %JAVA_HOME%\bin ao PATH.

Passo 2 – baixe o JRuby clicando no link Download e selecionando a versão mais atual. Descompacte o arquivo em um local de sua preferência. Crie uma variável de ambiente JRUBY_HOME que aponta para esse local e adicione o caminho %JRUBY_HOME%\bin ao PATH.

Passo 3 – Entre no site do SQLite3 e clique no link Download. Na seção “Precompiled Binaries for Windows” baixe os arquivos sqlite-<VERSÃO>.zip e sqlitedll-<VERSÃO>.zip (conforme dito anteriormente, a versão contemporânea a este tutorial é a 3.6.17). Crie um diretório no local de sua preferência denominado sqlite3. Descompacte os arquivos .zip baixados dentro desse diretório e configure a variável PATH para apontar para ele.

Passo 4 – Vamos testar o que instalamos até agora. Abra um prompt de comando e digite:

jruby -v

A versão do JRuby instalada no seu computador deve aparecer na tela. Digite agora a linha:

sqlite3

O SQLite3 será executado e ficará aguardando a entrada de comandos de administração. Digite “.exit” sem as aspas para sair do SQLite3.

Passo 5 – Vamos agora instalar o Rails. Abra o prompt de comando, digite a linha:

jruby -S gem install rails

e aguarde até o final da instalação. Quando ela terminar, digite:

jruby -S rails -v

para visualizar a versão do Rails instalada.

OBS: o parâmetro -S força o JRuby a procurar o script dentro da pasta “bin” ou na variável de sistema PATH.

Passo 6 – Precisamos instalar também o driver do SQLite3 para o JRuby. Isso pode ser feito digitando a seguinte linha no prompt de comando e pressionando ENTER:

jruby -S gem install activerecord-jdbcsqlite3-adapter

Lembrando de aplicar as configurações de proxy conforme visto anteriormente, caso necessário.

Passo 7 – Finalmente, criaremos uma aplicação de exemplo para testarmos o ambiente. Navegue pelo prompt de comando até o diretório onde você mantém suas aplicações e digite:

jruby -S rails teste

Edite o arquivo “config\database.yml” com a ajuda de um editor de textos. Na configuração do ambiente de desenvolvimento, altere o valor da propriedade “adapter” para “jdbcsqlite3”.

Entre no diretório “teste” e digite a seguinte linha para criar um cadastro de pessoas:

jruby script/generate scaffold Person name:string phone:string

Crie o banco de dados:

rake db:migrate

Inicie o servidor:

jruby script/server

E acesse o endereço “http://localhost:3000/people&#8221;. Se tudo deu certo, você verá a página que mostra as pessoas cadastradas no sistema.

IMPORTANTE: se a rede onde está seu computador possui configuração de proxy, é preciso passar essa configuração através do parâmetro -p do comando gem usando a seguinte sintaxe:

-p http://usuario:senha@servidorproxy:porta

Isso deve ser feito para todos os comandos de instalação de gems que foram vistos nesse tutorial. Use o seguinte exemplo como referência:

jruby -S gem install rails -p http://tarso:123@meu.proxy.com.br:4321

Quaisquer dúvidas e/ou correções, favor postar nos comentários. Até mais!

Configurando ambiente JRuby on Rails + SQLite3 no Windows