sexta-feira, 11 de novembro de 2011

Spring acessando Datasource do Tomcat

Recentemente fui implantar um sistema que utiliza Spring 3, JPA 2 e PrimeFaces 3 na Integrator.com.br, até ai nada de mais, a não ser por uma restrição do Integrator de não permitir que o Spring criasse o datasource, ele deveria ser criado pelo Tomcat.

Nada muito complexo também, no Spring basta declaramos um bean que apontará para o endereço JNDI do datasource a ser criado no Tomcat, algo assim:

     
 
Feito isso, basta criar o datasource no Tomcat. Para isso, precismos criar um arquivo XML com o mesmo nome da sua aplicação, vamos dizer que a aplicação no caso vai ser a "exemploApp", logo o arquivo a ser criado será o "exemploApp.xml". Neste arquivo configuraremos o datasource, algo assim (no exemplo é um banco Mysql):

     
      

Observe que o nome JNDI utilizado pelo bean do Spring é o mesmo para o datasource (name="jdbc/NomeQualquer").

Esse arquivo será copiado para dentro do Tomcat: %tomcat_home%/conf/Catalina/localhost/

Além disso, é preciso cópiar o Driver desejado para dentro das Libs do Tomcat (%tomcat_home%/lib).

E pronto, agora o Spring vai usar esse datasource sem maiores problemas.

Até.

terça-feira, 8 de novembro de 2011

Calcular distância GPS

Como se calcula a distância entre 2 pontos GPS? Precisei disso, achei que seria mole, mas não é não...
Felizmente temos muitas pessoas ajudando mundo a fora, e esse cara aqui colocou um código legal para isso: http://www.cesar.inf.br/blog/?p=273

Transcrevi para Java:
public static double distance(double p1Lat, double p1Lon, double p2Lat, double p2Lon) {
   double constant = 6371.0;
           
   p1Lat = p1Lat * Math.PI / 180.0;
   p1Lon = p1Lon * Math.PI / 180.0;
   p2Lat = p2Lat * Math.PI / 180.0;
   p2Lon = p2Lon * Math.PI / 180.0;
           
   double lat = p2Lat - p1Lat;
   double lon = p2Lon - p1Lon;
           
   double a = Math.sin(lat / 2) * Math.sin(lat / 2) + Math.cos(p1Lat) * Math.cos(p2Lat) * Math.sin(lon / 2) * Math.sin(lon / 2);
   double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
           
   return Math.round(constant * c * 1000); // resultado em metros.
}
A título de curiosidade, esse "6371" representa a curvatura da Terra... vivendo e aprendendo...

Até!

quarta-feira, 31 de agosto de 2011

PrimeFaces 3.0.M3 Released

Fonte: http://blog.primefaces.org/?p=141


Turkish Java EE and Agile Mentoring  Powerhouse Prime Technology is glad to announce the third milestone release of it’s leading JSF component suite, PrimeFaces. M3 is featuring over 140 improvements, 17 new components(9 reborn, 8 brand new), improved quality as a result of significant maintenance, better portlet support and much more.
  • New component: TimeLine
  • New component: FeedReader
  • New component: Sheet
  • New component: Subtable
  • New Chart Types: Donut, Bubble, MeterGauge, OHLC and Area.
  • Reimplemented AccordionPanel (Multiple selection, dynamic tab model)
  • Reimplemented TabView (Closable tabs, dynamic tab model)
  • Reimplemented Tooltip
  • Reimplemented ThemeSwitcher
  • Reimplemented Carousel
  • Reimplemented Dialog (Minimizable, Maximizable, Lazy mode)
  • Reimplemented ConfirmDialog
  • Reimplemented AutoComplete (dropdown mode, customizable content)
  • Reimplemented TreeTable (Ajax toggling, scrollable, resizable, events)
  • Improved support for multiple PrimeFaces portlets.
  • Important fixes to LazyLoading DataTable.
  • Introduced rowKey and SelectableDataModel for enhanced DataTable selection.
  • Customizable content for picklist.
  • Circle and Rectangle support for GMap.
  • ContextMenu integration with tree, treeTable and dataTable.
  • Scrolling improvements for datatable like horizontal scrolling and col resize.
  • MetaKey and Shift key support for multiple selection in datatable.
  • Major maintenance on fileUpload component.
  • Charting features like interactive legend, text rotation and more.
Reimplemented components are developed as native PrimeFaces widgets without using a third party plugin. We wanted to emphasize this, because there seems to be a common misunderstanding about how fast PrimeFaces evolves and provide so many features. It’s not because PrimeFaces always wraps third party widgets like jQuery UI, it is because PrimeFaces Team(outnumbered but passionate compared to competing other JSF libraries) puts so much time into this project including midnights and weekends.
See full list of changelog for detailed information and visit downloads section to try the new milestone. To assist PrimeFaces community during migration, we’ve initiated the 3.0 migration guide at PrimeFaces Wiki. Also up to date tag/attribute documentation is back in facelet taglib so your favorite IDEs can display quick documentation about tags and attributes via code completion. Please note that PrimeFaces User’s Guide for 3.0 will be available along with PrimeFaces 3.0 final release.

RoadMap
M3 is the last milestone release, next version will be 3.0.RC1 followed by 3.0 final featuring new ajax push features aka Prime Push, major updates to PrimeFaces Mobile, a couple of new components like orderList and major maintenance. We aim to fix all the defect reports in our issue tracker by 3.0.RC1. Tentative release date of 3.0.RC1 is early november.

segunda-feira, 18 de julho de 2011

Complexidade Ciclomática

Um dos problemas mais comuns apontados pelo nosso amigo Sonar é a alta complexidade ciclomática.  É uma medida “chata”, muitas vezes difícil de diminuir. Mas para diminuir, antes é preciso enteder como essa complexidade é calculada! Na Wikipedia temos uma definição bem simples e útil, em resumo:
“A complexidade ciclomática duma seção do código fonte é a quantidade de caminhos independentes pelo código. Por exemplo, se o código fontes não contém estruturas de controle senão sequenciais a complexidade é 1, já que há somente um caminho válido através do código. Se o código possui somente uma estrutura de seleção contendo somente uma condição, então há dois caminhos possíveis, aquele quando a condição é avaliada em verdadeiro, e aquele quando a condição é avaliada em falso.”
Ou seja, cada comando que provoca desvios, como if´s e switch´s, elevam a complexidade ciclomática de um trecho de código. Por exemplo, o código abaixo possui complexidade ciclomática igual a 1:
public void metodo(String abc) {
   System.out.println(abc);
}
Já o código abaixo teria complexidade igual a 2:
public void metodo(String abc) {
   if ( condicional ) {
      System.out.println(abc);
   }
}
E com um simples e inocente switch? A complexidade vai ser igual ao número de cases!!!
double getSpeed() {
    switch (_type) {
       case EUROPEAN:
          return getBaseSpeed();
       case AFRICAN:
          return getBaseSpeed() + getLoadFactor() * _numberOfCoconuts;
       case NORWEGIAN_BLUE:
          return (_isNailed) ? 0 : getBaseSpeed(_voltage);
    }
}
E esse (switch) é o caso mais perigoso! De maneira muito fácil ele eleva drásticamente a complexidade ciclomática.

E por que se preocupar? Porque quanto maior a complexidade maior vai ser a probabilidade de erros, maior a necessidade de testes (o ideal é que o número de testes fosse igual ao número da complexidade) e, principalmente, maior a probabilidade de alguém que estiver lendo ou alterando o código (manutenções) perder algum ‘detalhe’ importante. Ou seja, maior probabilidade de bugs e menor produtividade.

Complexidade
Classificação
Entre 1 e 10 Baixa complexidade. Fácil entender e testar.
Entre 11 e 20 Média complexidade. Relativamente difícil entender e testar.
Entre 21 e 50 Alta complexidade. Difícil entender e testar.
Maior que 51 Altíssima complexidade. Impossível entender e testar.

Mas o que fazer? Parar e pensar! Será que não podemos utilizar alguma outra alternativa? Que tal polimorfismo?

Ou quem sabe um strategy? O importante é não fugir muito da “borda“.

Até!

quarta-feira, 13 de julho de 2011

Agile Brazil – TDD

Um assunto muito abordado durante o Agile Brazil 2011 foi o Test-driven development (TDD). É um assunto que não domino e sempre tive curiosidade de estudar. Assisti algumas palestras/workshops e a idéia é realmente muito bacana, não é atoa que tem tanta gente utilizando por ai. Vou tentar passar uma visão geral, do pouco que aprendi, sobre TDD neste post.
A ideia é simples:
  1. Escreva o teste, ele vai falhar;
  2. Escreva o código, faça o teste passar;
  3. Refatore o código, pense no que escreveu, tente melhorar.

Pronto! Basta refazer esse ciclo a cada nova funcionalidade que deseja criar, e garanta que seu teste esteja. Mas para que fizemos isso? Será que é apenas para termos um percentual de teste maior? Será que realmente foi para garantir que o nosso sistema está sendo testado? Não! TDD não diz respeito apenas a teste, TDD é também uma técnica design!

Segundo Bob Martin, “The act of writing a unit test is more an act of design than of verification.  It is also more an act of documentation than of verification.” TDD pode encaminhar a um nível que possibilite um código mais modularizado, flexível e extensível. Este efeito surge devido a metodologia requerer que os desenvolvedores pensem no software em pequenas unidades que podem ser re-escritas, desenvolvidas e testadas independemente e integradas depois. Isto implica menores e mais classes, evitando o acoplamento e permitindo interfaces mais limpas (Wikipedia). Resumido por Martin Flower, “The benefit is that thinking about the test first forces you to think about the interface to the code first. This focus on interface and how you use a class helps you separate interface from implementation.

Em um dos workshops que participei, o pessoal do Caelum apresentou de maneira prática alguns bons exemplos de como o TDD pode nos ajudar a enxergar alguns problemas de design nas nossas aplicações. Por exemplo, nos deram o seguinte código, o qual é responsável por calcular salários dos funcionários de acordo com seu cargo e salário base:
import static br.com.caelum.tdd.exercicio1.Cargo.DBA;
import static br.com.caelum.tdd.exercicio1.Cargo.DESENVOLVEDOR;
import static br.com.caelum.tdd.exercicio1.Cargo.TESTADOR;

public class CalculadoraDeSalario {

   public double calcula(Funcionario funcionario) {
       if(DESENVOLVEDOR.equals(funcionario.getCargo())) {
          return dezOuVintePorCentoDeDescontoNo(funcionario);
       }
       if(DBA.equals(funcionario.getCargo()) || TESTADOR.equals(funcionario.getCargo())) {
          return quinzeOuVinteECincoPorCentoDeDescontoNo(funcionario);
       }
       throw new RuntimeException("funcionario invalido");
   }
   
   private double dezOuVintePorCentoDeDescontoNo(Funcionario funcionario) {
       if(funcionario.getSalarioBase() > 3000.0) {
          return funcionario.getSalarioBase() * 0.8;
       }
       else {
          return funcionario.getSalarioBase() * 0.9;
       }
   }

   private double quinzeOuVinteECincoPorCentoDeDescontoNo(Funcionario funcionario) {
       if(funcionario.getSalarioBase() > 2000.0) {
          return funcionario.getSalarioBase() * 0.75;
       }
       else {
          return funcionario.getSalarioBase() * 0.85;
       }
   }
}
public enum Cargo {
   DESENVOLVEDOR,
   DBA,
   TESTADOR
}
Que já possuia os testes unitários implementados:
public class CalculadoraDeSalarioTests {

 private CalculadoraDeSalario calculadora;

 @Before
 public void setUp() {
  calculadora = new CalculadoraDeSalario();
 }
 
 @Test
 public void deveRetornar4000MenosImpostosDe20PorCentoSeDesenvolvedorGanhaMaisDe3000(){
  Funcionario desenvolvedor = umFuncionario(DESENVOLVEDOR, comSalarioBase(4000.0));
  
  double salario = calculadora.calcula(desenvolvedor);
  
  assertEquals(4000.0 * 0.8, salario, 0.000001);
 }

 @Test
 public void deveRetornar1000MenosImpostosDe10PorCentoSeDesenvolvedorGanhaMenosDe3000(){
  Funcionario desenvolvedor = umFuncionario(DESENVOLVEDOR, comSalarioBase(1000.0));
  
  double salario = calculadora.calcula(desenvolvedor);
  
  assertEquals(1000.0 * 0.9, salario, 0.000001);
 }


 @Test
 public void deveRetornar4000MenosImpostosDe25PorCentoSeDBAGanhaMaisDe2000(){
  Funcionario dba = umFuncionario(DBA, comSalarioBase(4000.0));
  
  double salario = calculadora.calcula(dba);
  
  assertEquals(4000.0 * 0.75, salario, 0.000001);
 }

 @Test
 public void deveRetornar1000MenosImpostosDe15PorCentoSeDBAGanhaMenosDe2000(){
  Funcionario dba = umFuncionario(DBA, comSalarioBase(1000.0));
  
  double salario = calculadora.calcula(dba);
  
  assertEquals(1000.0 * 0.85, salario, 0.000001);
 }

 @Test
 public void deveRetornar4000MenosImpostosDe25PorCentoSeTestadorGanhaMaisDe2000(){
  Funcionario testador = umFuncionario(TESTADOR, comSalarioBase(4000.0));
  
  double salario = calculadora.calcula(testador);
  
  assertEquals(4000.0 * 0.75, salario, 0.000001);
 }

 @Test
 public void deveRetornar1000MenosImpostosDe15PorCentoSeTestadorGanhaMenosDe2000(){
  Funcionario testador = umFuncionario(TESTADOR, comSalarioBase(1000.0));
  
  double salario = calculadora.calcula(testador);
  
  assertEquals(1000.0 * 0.85, salario, 0.000001);
 }
 
  
 private Funcionario umFuncionario(Cargo cargo, double salario) {
  Funcionario funcionario = new Funcionario();
  funcionario.setNome("Martin Fowler");
  funcionario.setSalarioBase(salario);
  funcionario.setCargo(cargo);
  return funcionario;
 }
 

 private double comSalarioBase(double salario) {
  return salario;
 }
}
E pediram para que fosse inserido um novo cargo, “Gerente”, no qual deveria incidir imposto de 20% caso o salário base fosse acima de 5000, ou 15% caso contrário. Como você implementaria esse novo requisito? 100% dos participantes criaram o novo cargo na enumeração e adicionaram mais um If na calculadora, solução simples e rápida! E qual o problema disso?
  • Aumento da complexidade e da complexidade ciclomática;
  • Proliferação de if´s similares;
  • Sempre que um novo cargo surgir, alguém deverá lembrar de alterar a calculadora;
O próprio teste aponta os erros!
  • Observe o nome do teste: deveRetornar4000MenosImpostosDe20SeDesenvolvedorGanhaMaisDe3000 – Existe um condicional no nome do teste!
  • Existe um teste para cada cargo, mesmo estando todos juntos.
  • Grande quantidade de teste.
  • Essa classe não é coesa, ela faz muita coisa!
Não seria melhor implementar assim?
public interface CalculoDeImposto {
    double calculaImposto(Funcionario funcionario);
}
public class DezOuVintePorCento implements CalculoDeImposto {
    public double calculaImposto(Funcionario funcionario) {
       if(funcionario.getSalarioBase() > 3000) {
          return funcionario.getSalarioBase()*0.8;
       }
       else {
          return funcionario.getSalarioBase()*0.9;
       }
    }
}
E no enum:
public enum Cargo {
    DESENVOLVEDOR (new DezOuVintePorCento()),
    DBA (new QuinzeOuVinteECincoPorCento()),
    TESTADOR (new QuinzeOuVinteECincoPorCento()),
    GERENTE (new QuinzeOuVintePorCento());

    private CalculoDeImposto calculadoraImposto;
    Cargo(CalculoDeImposto calculadoraImposto) {
       this.calculadoraImposto = calculadoraImposto;
    }
   
    public CalculoDeImposto getCalculadora() {
       return calculadoraImposto;
    }
}
Com isso temos alguns ganhos:
  • Extrair cada responsabilidade para uma classe específica (Princípio da Responsabilidade Única).
  • Temos 3 estratégias de cálculo diferentes (10ou20%, 15ou25%, 15ou20%), cada uma deve estar em uma classe separada (Strategy?).
  • Utilize polimorfismo para que a cada novo cargo não precisemos lembrar de alterar uma classe para dar suporte.
Bom, apenas um pequeno exemplo. É um assunto que vale a pena uma lida e testar para ver os resultados.

Até!

terça-feira, 12 de julho de 2011

Agile Brazil – Clean Code

Uma das boas palestras que assisti no Agile Brazil 2011 dizia respeito à qualidade de código, intitulada de “Clean Code“, foi apresentada por Rodrigo Branas, mostrou algumas dicas/exemplos de como podemos melhorar nossos códigos e assim trabalhar de forma mais satisfatória.

A apresentação começou questionando o quanto um código mal escrito influencia na nossa satisfação profissional, o quão insatisfeitos ficamos como nos deparamos com códigos como esse abaixo (infelizmente esse código eu peguei em um projeto nosso, mas que foi internalizado, não coube tudo, são mais de 400 linhas nesse método):


E ai ele nos leva a refletir se a gente realmente se sente profissional quando vemos esses códigos. E mais, qual o preço para arrumar isso? E nas manutenções futuras, como vai ser manter isso? E quando tiver um Bug? Perdemos muito mais tempo lendo o código, tentando entender, do que realmente corrigindo, o que geralmente é apenas uma linha.


E a partir dai ele começa a introduzir alguns ‘conceitos’ do Clean Code: faça com cuidado, revele suas intenções, seja simples e direto, faça código legível (binário é para computadores lerem). A partir dai ele começa a aprofundar em alguns exemplos, bem simples, de como podemos melhorar.


O primeiro tópico diz respeito à escolha de nomes, abordando as limitações históricas (linguagens, monitores, etc) e a herança que trazemos. A grande dica é: revele suas intenções.


Não seja tão genérico!

 
Qual o tamanho ideal de um método? O menor possível!


Dentre outros assuntos, ainda foram abordados tópicos interessantes como: responsabilidade única, alta coesão, estruturas de decisão, magic numbers, distanciamento da margem, passagem de parâmetros, níveis de abstração e comentários, vários fatores que nos ajudam a ter um código de qualidade e, principalmente, legível.
Por fim, ele indica o uso de ferramentas para auxiliar nessa tarefa.


Há vários anos venho tentando "implantar" o uso de ferramentas de Integração Contínua com avaliação de código (o que agora chamam de Inspeção Contínua) aqui na empresa onde trabalho, mas sem grande sucesso. Não basta ter ferramenta se as pessoas realmente não entendem o valor, e isso é bem difícil de colocar na cabeça de alguns... Pelo menos deu pra ver que o que eu tento fazer a tanto tempo hoje é tido como uma boa prática e esta crescendo bastante.

Uma apresentação bem similar à utilizada está disponível aqui (ainda não foi disponibilizada a utilizada no evento). Vale uma olhada.
Até.

segunda-feira, 28 de março de 2011

Debug Remoto no OAS

Precisando debugar uma aplicação em um OAS (Oracle Application Server) remotamente utilizando o Eclipse? É possível e simples, segue os passos necessários para configurar o ambiente (não me responsabilizo por nada!).

Parte 1 - Configurar o OAS

Basta informamos para o OAS que queremos debugar a instância do OC4J que ele possui, que na verdade se resume em adicionar alguns parâmetros na inicialização o OC4J (que o próprio OAS inicializa), os parâmetros são:
  • -Xdebug
  • -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=4000
Esse valor 4000 corresponde à porta que será disponibilizada para se conectar remotamente ao OAS, pode ser alterado para o valor que melhor atender suas necessidades.

E para informamos esses parâmetros no OAS temos 2 opções:
  • Utilizar a interface gráfica do EM para configurar os parâmetros
  • Entrando no EM selecione qual a instância do OC4J desejas debugar, após isso vá na aba "Administração", depois selecione a opção "Propriedades do Servidor". Essa tela na verdade altera o arquivo opmn.xml se encontra no diretório $OAS_HOME/opmn/conf. Antes de tudo, recomendo um backup deste arquivo. 
    Agora basta configurar a parte "Parâmetros Start: Opções Java", adicionando os parâmetros informados anteriormente. Fica mais ou menos assim: 
    Configuração utilizando EM
    Pronto! Basta reiniciar a instância alterada (as vezes é necessário reiniciar o OAS inteiro).
     
  • Inserir os parâmetros diretamente no opmn.xml
  • O arquivo opmn.xml se encontra no diretório $OAS_HOME/opmn/conf. Antes de tudo, recomendo um backup deste arquivo.
    Devemos encontrar a tag referente à instância do OC4J que queremos debugar. Se quisermos debugar a instância home, por exemplo, devemos encontrar uma tag mais ou menos assim: <process-type id="home" module-id="OC4J" status="enabled"> Dentro dela teremos a tag onde estão os parâmetros utilizados para inicializar o OC4J: <category id="start-parameters">
    Agora basta adicionar os valores dos parâmetros informados acima na tag <data id="java-options" values="... os parâmetros vão aqui... " /> (cuidado para manter as informações anteriores), deve ficar mais ou menos assim:  
    <data id="java-options" value="-server -mx512M -ms64M -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=4000 -XX:AppendRatio=3 -Djava.security.policy=$ORACLE_HOME/j2ee/home/config/java2.policy -Djava.awt.headless=true -Dhttp.webdir.enable=false"/>
    Pronto! Basta reiniciar a instância alterada (as vezes é necessário reiniciar o OAS inteiro).
     
Parte 2 - Configurar o Eclipse

Uma vez configurado o OAS agora vamos fazer o Eclipse se conectar para debugar as aplicações. Para isso basta criarmos uma "Remote Java Application", para isso vá no menu "Run -> Debug Configurations...". Abrirá uma janela igual a apresentada abaixo. Nela devemos selecionar o projeto que queremos debugar, o tipo de conexão (Socket Attach), o IP do Host (do servidor OAS no caso) e a porta (aquele 4000 la de cima).

Configuração do Eclipse

Pronto! Agora é só rodar e já vai estar debugando! Basta colocar os breakpoints e navegar direto no host do OAS.