terça-feira, 18 de dezembro de 2012

Controle transacional: Spring + Vraptor

Controle de transação é sempre um ponto crítico em qualquer aplicação. Iniciar, tratar falhas e finalizar transações manualmente pode ser muito complicado, portanto muitas vezes usamos algum framework ou prática já consolidada para abordar o problema.

Em aplicações web uma abordagem muito utilizada é "uma transação por requisição", que consiste em abrir uma transação a cada requisição feita e no fim da lógica da requisição podemos efetuar o commit caso tudo tenha acontecido como esperado ou efetuar um rollback.

Note que você pode fazer isso em todos os seus servlets ou métodos dos controllers do seu framework mvc, mas dessa forma a tarefa será repetitiva e de difícil manutenção. Para melhorarmos o cenário, caso esteja trabalhando com uma aplicação usando uma api mais baixa como Servlets é possível usar um filter para implementar essa funcionalidade.

Com o Vraptor temos essa funcionalidade pronta, veja a documentação e o código. Se seguirmos a apostila oficial veremos que neste caso o Vraptor gerencia a SessionFactory, a Session e também nossos DAOs.

A motivação deste post foi um cenário encontrado em um projeto onde já possuíamos tudo gerenciado pelo Spring, inclusive transações e DAOs, não gostaríamos de refatorar tudo e ainda assim tirar proveito da abordagem de uma transação por requisição. Para quem quiser acompanhar como chegamos a solução segue o link do post no guj: http://www.guj.com.br/java/224207-vraptor3--hibernate--transactional-na-controller/4

Vamos ao código:




  
  
  
  
 

 
  
  
  
   
    true
    true
    org.hibernate.dialect.MySQLDialect
    update
    true
   
  


 
  
 



Este é o applicationContex.xml usado na aplicação, apenas declaramos o dataSource, nossa sessionFactory e também um transactionManager. Nada diferente de qualquer aplicação Spring normal.

Criamos um DAO genérico:
public abstract class GenericDAOHibernate<T> {

 protected SessionFactory sessionFactory;

 private final Class<T> persistentClass;

 @Autowired
 public GenericDAOHibernate(SessionFactory sessionFactory) {
  this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass())
    .getActualTypeArguments()[0];

  this.sessionFactory = sessionFactory;
 }

 public T load(Long id) {
  return (T) this.getSession().get(this.persistentClass, id);
 }
       
        // outros métodos...

}
Uma implementação do nosso DAO
@Repository
public class UserDAOHibernate extends GenericDAOHibernate {

 @Autowired
 public UserDAOHibernate(SessionFactory sessionFactory) {
  super(sessionFactory);
 }

 @Override
 public User getUserByLogin(String login) {
  //...
 }
        // outros métodos...

}

E por fim o nosso interceptador de transações:


@Intercepts
public class SpringTransactionInterceptor implements Interceptor {

 private PlatformTransactionManager transactionManager;

 private final Validator validator;

 public TransactionInterceptor(PlatformTransactionManager transactionManager, Validator validator) {
  this.transactionManager = transactionManager;
  this.validator = validator;
 }

 @Override
 public void intercept(InterceptorStack stack, ResourceMethod method, Object resourceInstance)
   throws InterceptionException {

  TransactionDefinition def = new DefaultTransactionDefinition();
  TransactionStatus status = transactionManager.getTransaction(def);

  try {
   stack.next(method, resourceInstance);
   if (!validator.hasErrors()) {
    transactionManager.commit(status);
   }
  } finally {
   if (!status.isCompleted()) {
    transactionManager.rollback(status);
   }
  }

 }

 @Override
 public boolean accepts(ResourceMethod method) {
  return true;
 }
}
Note que você pode tanto neste interceptor, quanto no padrão do Vraptor, sobreescrever os comportamentos. Um exemplo seria interceptar apenas métodos anotados com uma anotação própria.

Você pode baixar esta classe na forma de plugin no Github de contribuições do Vraptor ou no meu particular.

 Caso tenha alguma dúvida é só entrar em contato.

segunda-feira, 15 de outubro de 2012

Melhorando o cenário de testes com padrões de projeto Builder e Fluent Interface

Como sabemos, testar garante que nosso código tenha mais qualidade, seja mais conciso e elegante e também conhecemos a importância de testar nossas aplicações. Porém testar gera mais código e devemos dar ao código de teste a mesma atenção que damos ao código de produção, para que os testes sejam fáceis de entender e não se tornem difíceis de serem mantidos. Pois caso isso aconteça a equipe pode ficar desmotivada para realizar os testes.

Imagine que estamos desenvolvendo um sistema para uma loja de venda de computadores. Este sistema deve sugerir computadores que possam agradar determinado cliente.

Um possível modelo para este domínio pode ser visto no diagrama (diagrama informal, ok?!) abaixo:
Nosso computador possui apenas duas portas USB, uma dianteira e outra traseira, cor, possui vários componentes e também informa se é de marca famosa, pois possuímos clientes que compram apenas produtos de primeira linha.

Cada componente possui nome, descrição e cor.

Cor por sua vez possuí um nome e valores correspondente a tabela de cores RGB (red, green, blue).

Vamos ao código do domínio:


public class Computador {
 private USB usbDianteira;

 private USB usbTraseira;

 private Collection< Componente > componentes;

 private boolean marcaFamosa;

 public Computador(USB usbDianteira, USB usbTraseira, Collection< Componente > componentes, boolean marcaFamosa) {
  this.usbDianteira = usbDianteira;
  this.usbTraseira = usbTraseira;
  this.componentes = componentes;
  this.marcaFamosa = marcaFamosa;
 }

 // getters e setters necessários

}


public class USB {
 private String versao;

 public USB(String versao) {
  this.versao = versao;
 }

 // getters e setters necessários
}


public class Componente {
 private String nome;

 private String descricao;

 private Cor cor;

 public USB(String nome, String descricao, Cor cor) {
  this.nome = nome;
  this.descricao = descricao;
  this.cor = cor;
 }

 // getters e setters necessários
}


public class Cor {
 private String nome;

 private int r;

 private int g;

 private int b;

 public USB(String nome, int r, int g, int b) {
  this.nome = nome;
  this.r = r;
  this.g = g;
  this.b = b;
 }

 // getters e setters necessários
}


Agora que temos nosso modelo pronto, iremos testar a classe que verifica se devemos sugerir determinado computador ao cliente ou não. Esta classe recebe o Cliente no construtor e podemos chamar o método deveSugerir, que recebe um computador e retorna um boolean.

public class Aconselhador {
 private Cliente client;
 
 public Aconselhador(Cliente cliente) {
  this.cliente = cliente;
 }

 public boolean deveReceberComoSugestao(Computador computador) {
  // faz uma lógica baseada no cliente no computador a ser sugerido
 }
}
Vamos testar nossa classe, para fins didáticos vamos testar apenas um caso da classe, porém em seu código, você deve testar TODAS as possibilidades. (Veja o post anterior para aprender como visualizar a cobertura de testes em seu código).

@Test
public void deveSugrirComputadorDeMarcaEComMuitosComponentesParaClienteExigente() {
 Cliente cliente = new Cliente("Renan");

 USB usbDianteira = new USB("2.0");
 USB usbTraseira = new USB("1.0");

 Cor corDoMonitor = new Cor("preto", 0, 0, 0);
 Componente monitor = new Componente("nome do monitor", "descricao monitor", corDoMonitor);

 Cor corDoMouse = new Cor("preto", 0, 0, 0);
 Componente mouse = new Componente("descricao do mouse", "nome mouse", corDoMouse);

 Cor corDoTeclado = new Cor("branco", 100, 100, 100);
 Componente teclado = new Componente("nome do teclado", "descricao teclado", corDoMonitor);

 Cor corDaWebCam = new Cor("cinza", 140, 120, 110);
 Componente webCam = new Componente("nome da webcam", "descricao webcam", corDaWebCam);

 List< Componente > componentes = new ArrayList<>();
 componentes.add(monitor);
 componentes.add(teclado);
 componentes.add(webCam);

 Computador computador = new Computador(usbTraseira, usbDianteira, componentes, true);

 assertTrue(new Aconselhador(cliente).deveReceberComoSugestao(computador));
}

Vamos analisar o código e fazer algumas considerações. A primeira coisa a notar é que quanto mais Componentes nosso Computador possuir, mais poluído fica nosso código. Também sem uma explicação prévia, fica difícil saber oque é o cada argumento inteiro passado para o construtor da classe Cor, o mesmo acontece para o argumento boolean passado para o construtor de Computador. Note que apenas lendo o código de teste não temos a mínima ideia do que significa cada um desses argumentos.

Note que instanciar tantos objetos, com tantas relações se torna propenso a erros.

Nosso Computador recebe uma Collection de Componentes, logo podemos declarar um Componente porém podemos esquecer de passá-lo para a lista de Componentes passada ao Computador. Como aconteceu com o componente "mouse", outro erro é que o objeto corDoMonitor foi passado como parâmetro para o construtor do teclado, repare o código.

Por fim, nosso Computador recebe dois argumentos do tipo USB, porém oque significa o primeiro? E o segundo? Qual deles representa a USB dianteira, e qual da USB traseira? No código acima, invertemos a ordem das USB.

Veja que este é um ponto bem propício a erros: é difícil saber a ordem quando temos dois ou mais argumentos do mesmo tipo sendo recebidos. O mesmo acontece com a classe cor, qual a ordem de tons ela recebe? Vermelho, verde, azul? Apesar de fugir da convenção nada impediria ser Verde, vermelho, azul, por exemplo. E também nos atributos String recebidos pela classe Componente.

É impossível apenas ler o código que cria o cenário de teste e entender todas as informações.

Porém podemos reverter essa situação com a aplicação dos padrões de projeto Builder e Fluent Interface.

O Builder torna a criação dos objetos mais fácil. Nos ajuda através de métodos com nomes significativos a entender oque estamos declarando e elimina as ambiguidades que podem ocorrer na passagem de parâmetros com o mesmo tipo, como no caso dos parâmetros USB na classe Computador e int na classe Cor.

Com Fluent Interface é possível dar mais fluidez à sintaxe e em alguns casos economizar boas linhas de código.

Vamos aos exemplos práticos. Começamos criando a classe ComputadorBuilder:

public class ComputadorBuilder {
 private USB usbDianteira;

 private USB usbTraseira;

 private List< Componente > componentes = new ArrayList<>();

 private boolean possuiMarcaFamosa;

 public ComputadorBuilder comUSBDianteira(USB usbDianteira) {
  this.usbDianteira = usbDianteira;
  return this;
 }

 public ComputadorBuilder comUSBTraseira(USB usbTraseira) {
  this.usbTraseira = usbTraseira;
  return this;
 }

 public ComputadorBuilder comMarcaFamosa() {
  this.possuiMarcaFamosa = false;
  return this;
 }

 public ComputadorBuilder comComponente(Componente componente) {
  this.componentes.add(componente)
  return this;
 }

 public Computador build() {
  return new Computador(this.usbDianteira, this.usbTraseira, this.componentes, possuiMarcaFamosa);
 }
}


Veja que todos os métodos começam com a palavra "com", convencionamos assim, para que fique mais fácil autocompletar o nome dos métodos através da ide.

Vamos ao builder da classe Componente:

public class ComponenteBuilder {

 private String nome;

 private String descricao;

 private Cor cor;
 
 public ComponenteBuilder comNome(String nome) {
  this.nome = nome;
  return this;
 }

 public ComponenteBuilder comNome(String descricao) {
  this.descricao = descricao;
  return this;
 }

 public ComponenteBuilder comCor(Cor cor) {
  this.cor = cor;
  return this;
 }

 public Componente build() {
  return new Componente(this.nome, this.descricao, this.cor);
 }
}

E por fim o builder da classe Cor:

public class CorBuilder {

 private String nome;

 private int r;

 private int g;

 private int b;

 public CorBuilder comNome(String nome) {
  this.nome = nome;
  return this;
 }

 public CorBuilder comR(int r) {
  this.r = r;
  return this;
 }

 public CorBuilder comR(int g) {
  this.g = g;
  return this;
 }

 public CorBuilder comB(int b) {
  this.b = b;
  return this;
 }

 public Cor build() {
  return new Cor(nome, r, g, b);
 }
}

Agora vamos refatorar nosso teste, note que podemos encadear a chamada de nossos builders, criando assim uma fluidez ainda maior.

@Test
public void deveSugrirComputadorDeMarcaEComMuitosComponentesParaClienteExigente() {
 Computador computador = new ComputadorBuilder()
   .comUSBDianteira(new USB("2.0"))
   .comUSBTraseira(new USB("1.0"))

   .comComponente(new ComponenteBuilder()
    .comNome("nome do monitor")
    .comDescricao("descricao monitor")
    .comCor(new CorBuilder()
     .comNome("preto")
     .comR(0)
     .comG(0)
     .comB(0)
     .build()
    )
    .build()
   )

   .comComponente(new ComponenteBuilder()
    .comNome("nome do mouse")
    .comDescricao("descricao mouse")
    .comCor(new CorBuilder()
     .comR(0)
     .comG(0)
     .comB(0)
     .build()
    )
    .build()
   )


   .comComponente(new ComponenteBuilder()
    .comNome("nome do teclado")
    .comDescricao("descricao teclado")
    .comCor(new CorBuilder()
     .comR(100)
     .comG(100)
     .comB(100)
     .build()
    )
    .build()
   )


   .comComponente(new ComponenteBuilder()
    .comNome("nome webcam")
    .comDescricao("descricao webcam")
    .comCor(new CorBuilder()
     .comR(140)
     .comG(120)
     .comB(110)
     .build()
    )
    .build()
   )


  .build();

 Cliente cliente = new Cliente("renan");

 assertTrue(new Aconselhador(cliente).deveReceberComoSugestao(computador));
}

Apesar de nosso teste ter ficado com um número de linhas bem maior depois de refatorado, ganhamos muita expressividade, qualquer pessoa que ler o código entenderá o significado de cada argumento passado. E também ganhamos mais velocidade na hora de criar os objetos, decorrente da expressividade.

Bônus:
Padrões de projeto são como receitas, podemos segui-los, porém podemos adicionar nossos ingredientes a gosto, ou seja, não existe uma única forma de implementar um padrão. Note que usamos duas instâncias da classe Cor idênticas. Apesar de não estar descrito na do padrão builder, podemos criar um método estático para retornar um objeto com características fixas que usamos com frequência.

Algo como:
public static Cor corPreta() {
 return new Cor("preto", 0, 0, 0);
}

domingo, 12 de agosto de 2012

Colorindo seu código para garantir qualidade instantânea com EclEmma

O TDD nos ajuda a desenvolver código coeso e influencia no design do nosso código, o tornando melhor, além de obviamente garantir testes de nossas funcionalidades.

Podemos também utilizar ferramentas de métricas e cobertura de código para garantir a qualidade de nosso projeto. Como por exemplo o Cobertura, uma ferramenta que mede o percentual de linhas cobertas por testes em nosso código.

Durante a fase de testes e desenvolvimento podemos querer saber de forma prática oque nossos testes estão cobrindo e onde esquecemos de testar, especialmente quando estamos trabalhando com código legado. Seria excelente se ao rodarmos um teste, a IDE já nos fornecesse essa informação.

Felizmente existem plugins que conseguem fazer este trabalho. Dentre eles o eCobertura e o EclEmma.

Vou demonstrar o uso do EclEmma através de um exemplo trivial.

O primeiro passo é instalar o plugin no Eclipse, para isso vá ao Marketplace do Eclipse (Help > Marketplace...), busque por eclemma e clique em install. A partir daí é só realizar os passos de uma instalação de plugin normalmente.

Agora vamos escrever um simples código para entender o funcionamento.

Vamos escrever testes para a classe legada Calculadora, esta possui um método chamado calcula, que dado um valor e um boolean decide se soma mais 10 ao valor.

Se o valor for maior que 100 ou o boolean passado seja true, então soma-se 10 ao valor, caso contrário não faz nada.

public class Calculadora {

 public double calcula(double valor, boolean aplicaTaxas) {
  double valorCalculado = valor;
  
  if(valor > 100 || aplicaTaxas) {
   valorCalculado += 10;
  }
  
  return valorCalculado;
 }
 
}

Vamos escrever nosso primeiro teste:

 @Test
 public void naoDeveCalcularPoisValorEMenorQue100ENaoAplicaTaxas() {
  Calculadora calc = new Calculadora();
  
  double valorCalculado = calc.calcula(80, false);
  
  assertTrue(valorCalculado == 80);
 }

Para rodar o teste com o plugin clique com o direito sobre o arquivo de testes ou em seu código e vá a opção Coverage as... JUnit Test, pelo atalho Alt + Shift + E e T.

Navegue até a classe calculadora e veja como nosso código ficou colorido:



Repare que as linhas cobertas pelo teste ficaram verdes, com exceção da linha 7, que está amarela e da linha 8, que está vermelha.

Isso significa que a linha 7 não foi totalmente testada, ou seja, depois de rodar o teste, todas suas condições não foram realizadas (passe o mouse sobre o losango para ver a dica).

Vamos criar mais um teste para entrarmos na condicional. Agora passando o valor como 110 e aplicaTaxas como false:

 @Test
 public void deveCalcularPoisValorEMaiorQue100() {
  Calculadora calc = new Calculadora();
  
  double valorCalculado = calc.calcula(110, false);
  
  assertTrue(valorCalculado == 120);
 }

Vamos ao resultado:



Note que a linha 8, que antes era vermelha, agora está verde, conseguimos criar um teste que cobre este caso. Porém a linha 7 ainda está amarela (passando o mouse sobre o losango vemos que falta apenas uma condicional não coberta).

Vamos à um ultimo teste que simula o cenário ainda não coberto: Passar o parâmetro aplicaTaxas como true.

 @Test
 public void deveCalcularPoisAplicaTaxas() {
  Calculadora calc = new Calculadora();
  
  double valorCalculado = calc.calcula(20, true);
  
  assertTrue(valorCalculado == 30);
 }


Pronto, nossa lógica foi completamente testada.



Um excelente exercício que fiz foi desenvolver essa mesma classe usando TDD. Conforme você desenvolve o teste e codifica a implementação, já tem automaticamente 100% de cobertura. Porém se tivesse tomado essa abordagem não conseguiria mostrar como a ferramenta ajuda colorindo as linhas não testadas.

segunda-feira, 27 de fevereiro de 2012

Como configurar um projeto web com Maven + Eclipse

Algum tempo atrás estava procurando como configurar a dupla Eclipse + Maven para um projeto web e não consegui encontrar em um único site as instruções para realizar a tarefa, então estou escrevendo este guia para auxiliar os desenvolvedores com a mesma dificuldade.

Uso o Maven apenas para gerenciar as dependências, portanto a configuração realizada foi a mais simples possível para rodar o projeto.

O primeiro passo é instalar o m2e. Caso esteja usando o Eclipse Indigo basta ir no menu Help, depois Eclipse Market Place. Digite na caixa de busca m2e e instale o plugin.

O próximo passo é criar um Maven Project. Vá em File, New, Other e então procure por Maven Project.

Selecione a opção Create a simple project. Preencha o Group Id e Artifact Id do projeto, em Packing escolha a opção war, por se tratar de um projeto web.



Com o projeto criado, clique com o direito no projeto e escolha Properties >> Project Facets >> Convert to faceted from...

Marque a opção Dynamic Web Module.

Clique em Further Configuration avaliable e altere o Content Directory para: /src/main/webapp. Pressione OK.



Agora faremos com que as libs gerênciadas pelo maven sejam incluidas no deploy. Vá novamente nas propriedades selecione Deployment Assembly >> Add >> Java Build Path Entries >> Maven Dependencies.



Pronto! Agora é só adicionar suas dependências no pom.xml.

Abraços

segunda-feira, 6 de fevereiro de 2012

Query polimorfica com interfaces - Hibernate

Fazer uma query polimórfica em entidades relacionadas através de herança é muito simples. Porém as vezes desejamos executar uma query que busque todas as entidades que possuem determinado comportamento em comum, mas que não são da mesma hierarquia. Aqui é comum ver o desenvolvedor implementar herança de maneira errônea, apenas para conseguir esta funcionalidade.

Obs: Este tópico possui uma ótima discussão à respeito de herança e como ela pode ser prejudicial ao seu código.

Vamos supor que tenhamos o conceito de notificável em nosso sistema e queremos buscar por todas as entidades "notificáveis".

Como posso ter diversas entidades notificáveis que não fazem parte de uma hierarquia seria um erro usar herança. Então implementamos Notificavel como uma interface.


public interface Notificavel {

    public void notifica();

}



Suponhamos que temos duas entidades em que serão notificáveis: Sistema e Pessoa.


@Entity

public class Sistema implements Notificavel { ...



@Entity

public class Pessoa implements Notificavel { ...




Então realizamos a busca com a seguinte HQL:

String hql = "FROM br.com.renan.domain.Notificavel";


Note que colocamos o nome totalmente qualificado da interface, isso é necessário para que o hibernate saiba exatamente por qual interface buscamos.

Note que assim você consegue buscar por todas as entidades que implementem a inteface.

E por fim o teste:


@Test

public void deveRetornarDoisVeiculos() {

    List notificaveis = notificador.lista();

    assertEquals(2, notificaveis.size());

}


Aqui é possível encontrar o código completo do projeto.

Abraços.