DESENVOLVENDO PARA ANDROID: NOTIFICAÇÕES.

Opa galera, depois de tanto tempo, estou voltando para escrever um post rápido sobre android. Que são as notificações, lugares onde possam ser armazenados pequenas mensagens de aviso para o usuário.

Para criar uma nova notificação basta dar inicializar a classe Notification. Ela pode receber no construtor uma imagem, texto e o momento em que ela foi criada. Para mais informações consulte a documentação do Android.


Notification notification = new Notification(R.drawable.imagem, message, System.currentTimeMillis());

Ela deve conter a ação no qual ocorrerá quando ela for selecionada. Então ela deve conter uma Intent para saber o que fazer quando isso ocorrer. Um ponto pra ser reparado é o fato de colocar a flag Intent.FLAG_ACTIVITY_NEW_TASK na Intent. Assim ela iniciará uma nova Activity a sua escolha.


Intent notificationIntent = new Intent(ctx, Activity.class);

PendingIntent contentIntent = PendingIntent.getActivity(ctx, 0, notificationIntent, Intent.FLAG_ACTIVITY_NEW_TASK);

A seguir o exemplo completo:


Notification notification = new Notification(R.drawable.imagem, message, System.currentTimeMillis());

 

Intent notificationIntent = new Intent(ctx, Activity.class);

PendingIntent contentIntent = PendingIntent.getActivity(ctx, 0, notificationIntent, Intent.FLAG_ACTIVITY_NEW_TASK);

 

//Aqui adicionamos o efeito de vibrar ao adicionar a notificação. Lembrando que para isso, precisamos adicionar a permissão:

//<uses-permission android:name="android.permission.VIBRATE"></uses-permission> no AndroidManifest.xml

notification.defaults |= Notification.DEFAULT_VIBRATE;

long[] vibrate = {0,100,200,300};

notification.vibrate = vibrate;

&nbsp;

//Aqui estamos setando o título para a notificação e o texto que será exibido

notification.setLatestEventInfo(ctx, "Título", message, contentIntent);

&nbsp;

//Aqui estamos configurando o controle das notificações. Para isso você pega um serviço do sistema

NotificationManager manager = (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE);

//Então é só exibir a notificação pronta no sistema

manager.notify(idNoty, notification);

Publicidade

REFACTORING – Caso Real e boas maneiras Parte IV (Keep Walking…)

Essa semana tive que resolver um bug na feature dos posts anteriores. Acabei esquecendo um caso que caia em uma Exception, mas não vamos tocar no assunto :).

O caso é o seguinte, como dito anteriormente, aconteceu que eu tive que manter esse código, corrigir a falha como dito anteriormente e porque não refatorar mais um pouco?

E o caso da refactoring de hoje, tem um tema central que é o uso excessivo de getters e setters (aquele mesmo que você usa, não sabe o porque, e todo mundo acha que está certo. Amém.).

Um amigo meu defende: “porque usar todos os atributos privados, se tem um método get e set para cada. Usa todos os atributos públicos e pronto. Muito mais elegante”. Bem, eu concordo e não concordo. O uso excessivo de getters e setters, no qual eu já defendi como correto(#fail pra mim), é prejudicial. Mesmo se você não precise, e não saiba o porque, você vai criar um. As vezes por costume, ou o framework usado no seu projeto obrigue. Mas enfim, vamos usá-los quando preciso, respeitando o encapsulamento. Fundamento da OO muitas vezes esquecido.

Então, como fazer? Como diz o Guilherme Silveira na palestra sobre design de código. No meu código, eu tenho um objeto que sempre terá um atributo. O que eu faço para que esse meu objeto sempre tenha esse atributo ao criá-lo? Colocar no construtor? Muito bem, é isso mesmo. Adicionando os atributos no construtor, muito dos setters serão inúteis, então só deletá-los.

Pois então vemos como ficou o nosso código. Focando no método carregar a lista de objetos para o relatório.

Repare em todos os setters que estão listados para “montar” o objeto, para então ser passado a lista. Repare que sempre eu passo mais um objeto do tipo ProdutividadeFisioterapeuta como parâmetro nos métodos, algo está errado. Enquanto na classe ProdutividadeFisioterapeuta.java está o clássico construtor sem parâmetros, chamando o método super() da classe Object. E repleta de getters e setters. Não vou listar a classe, mas acredite, eles estarão lá.

Pois então, vamos criar nosso construtor inteligente na classe ProdutividadeFisioterapeuta.java.

Perceba a clareza que ficou o nosso construtor em relação a bagunça anterior.

Vamos ver como ficou o método da listagem 1, após a refatoração.

Indo pro histórico do github, vemos ai o resultado. 42 linhas a menos e mais clareza no código.

E claro ia esquecendo do mais importante, retirar os setters inúteis. Após excluir os setters, substituí em outros locais do código onde eu os utilizava, como nos testes de integração da classe. Após o último commit:

Finalizando, como tenho dito, sempre você vai ter que manter seu código e se possível sempre tente melhorá-lo. Talvez um dia você olhe para o código e não encontre nada para melhorá-lo. Bem, eu nunca tive esse privilégio. Então é isso, mais um caso prático de como melhorar seu código. Excelente dica: Como não aprender OO com java. Excelente post da caelum.

Até mais e bons estudos.

REFACTORING – Caso Real e boas maneiras Parte III (Soluções)

Bem, citamos várias falhas no post anterior. Vamos tentar resolver a replicação da lógica de negócio. Primeiro nossa classe ProdutividadeService.java possui outras responsabilidades além de realizar esses cálculos. Assim ferindo um princípio básico na Orientação a Objeto, o SRP(link) (Single Responsability Principle). Vamos levar toda essa lógica para uma classe apropriada que tenha apenas essa missão.

Coesão ++.

Então, toda essa regra se trata de calcular um intervalo de tempo que irá ser considerado no meu relatório. Então criamos a classe Intervalo.java, onde as regras serão centralizadas. Estamos criando algo novo, então estamos utilizando TDD. A seguir um exemplo de teste implementado na classe IntervaloTest.java.

Listagem 1. Exemplo de método de teste

Claro, para chegar nesse nível de legibilidade não foi de repente. Escrevemos códigos ruins, e melhoramos gradativamente. Todos os passos de refatoração de sua classe vale para testes. Mais pra frente, mostrarei uma boa prática na escrita de testes.

Ao final, temos como resultado a classe Intervalo.java:

Listagem 2.

O método intersecao() será aquele utilizado para calcular o intervalo em si. Para cada if mostrado anteriormente temos um booleano que representa os casos que devem ser levados em conta, consequentemente, os casos abordados pelos testes. Para cada condicional atendido, um novo intervalo será retornado levando em conta a dataInicial e dataFinal coerentes.

Como curiosidade, vemos que com a utilização do TDD, um caso novo foi incluído(o caso de um intervalo não interceptar o outro. Por exemplo, o intervalo usado como referencia for no período de junho e o outro intervalo está em um mês diferente. Retornamos null), e mesmo assim temos menos ifs explicitando cada caso e mesmo assim os testes são atendidos.Dessa forma excluímos código desnecessário, diminuindo ainda mais o número de linhas sem prejudicar no entendimento.

Também não criamos os famosos getters e setters  para cada atributo da classe. Bem, os getters foram utilizados, mas os setters não tivemos necessidade graças ao construtor inteligente da classe.

Encapsulamento ++.

Mas onde a classe intervalo sera usada? Adicionamos na classe CargaHorária.java e Produtividade.java, eles terão um Intervalo (composição).

Todos os métodos replicados serão excluídos:

Listagem 3. Resultado na classe CargaHoraria.java

Método calculaHoras foi movido para a classe CargaHoraria, trazendo a responsabilidade para uma entidade mais apropriada. Mas ainda vemos o que melhorar, como a extensão dos nomes, os métodos doubleValue(), a extensão das listas de parâmentros, mas ainda não acabamos.

Listagem 4. Método calculaHoras.. na classe ProdutividadeService depois da refatoração:

Todo aquele código foi excluído, restando apenas esse trecho. Lindo!

Tirei um print screen com o log do github:

Isso mesmo, 102 linhas de código inúteis a menos, que agora não mais atormentarão. E o sistema ainda fazendo o que deve fazer com testes cobrindo qualquer modificação minha.

A primeira etapa de refatoração concluída, vemos que ganhamos bastante, código desnecessário foi deletado, regra de negócio centralizada, a feiosa cascata de ifs também excluída, algumas renomeações feitas. Mas há ainda o que melhorar.

A utilização de métodos estáticos pra mim soa estranho, quase a OO tem um derrame ao utilizer esses métodos ditos genéricos, que nós criamos. Para isso vamos extrair o método de calculo de Dias em um Período, da classe DataUtil.java, para a classeIntervalo.java.


Double numeroDeDias = intersecao.getQuantidadeVezesOsDiasDaSemanaApareceramNoPeriodo(capturaDiasDaSemana()).doubleValue()

Integer aparicoesNoIntervalo(List<DiaDaSemana> dias);

Ok, mas dando uma olhada no método calculaHoras() na classe CargaHorária.java,  se eu tenho duas propriedades da classe interseção passadas como parâmetro, porque não levar esse método para a classe Interseção. Já resolve o problema da longa lista de parâmetros, prejudicial na legibilidade do método. Além do método capturaDias(), além de não dizer nada, percebeu que ele era inútil, olhe que maravilha, mais código desnecessário excluído.

Listagem 5. Método calculaHoras.. na classe ProdutividadeService.java

Mais algumas renomeações e extrações, percebemos que se tornaria ainda mais legível, levar o método calculaHoras() para Produtividade.java. A responsabilidade de calcular horas realmente deve ser dessa entidade. Um simples cast resolveu aqueles métodos doubleValue().

Design ++.

E por fim, não basta refatorar a classe, os testes terão que ser mantidos. Uma olhada nessa bizarrice feita por mim.

Nunca é legal você entupir os métodos com asserts. Reduza o número deles, assim você diminui a responsabilidade de cada método de teste e modularize seus testes, cada um testando determinada unidade de código.

Mas como fazer? Ai aparece uma prática simples, em que eu particularmente dava valor: Sobrescreva o equals() e o hashCode(). Olha que maravilha. Ao invés de criar uma assertiva para cada atributo do objeto. Crie um objeto com os resultados esperados. Assim apenas um assert é criado, realizando todos os comparativos feitos acima. Código a seguir:

OBS: Pra quem estreanhou, eu estar falando de Funcionário e depois apareceu Fisioterapeuta.Mude apenas a nomenclatura. Eu estava tentando generalizar os exemplos mas espero que não tenha prejudicado o entendimento. Qualquer coisa mandem feedbacks.

Link para a parte I.

Link para a parte II.

Abraço pessoal. Bons estudos e espero ter compartilhado uma experiência bacana.

REFACTORING – Caso Real e Boas Maneiras: Parte II (Bad Smells)

Para começar, não vou citar uma receita de bolo, mas esses três passos já são um começo para que você refatore sem medo.

I)              Entenda sua regra de negócio: Pelo o que tenho notado, essa etapa não é dita na maioria dos tutoriais e livros, mas pra mim é de suma importância. Como você vai implementar algo em que não conhece ou o conceito não esteja “no sangue”? Bem, o Diniz fala que não tem problema, apenas ele vai levar um tempo maior para resolver o problema. Enfim, eu acho uma etapa importante, pois o raciocínio fluirá mais facilmente e não será preciso muitas voltas para resolver o problema.

II)            Crie testes automatizados para o seu código legado.

III)          Se for necessário criar algo novo,  use TDD.

IV)          REFATORE!

Então, temos os passos, vamos entender nosso problema.

I) Regra de Negócio. O código foi retirado de um sistema que já está em produção, portando é um código verídico(sim, eu consegui fazer!). Eu devia popular um objeto para ele ser repassado para um relatório que calcularia a produtividade de um funcionário. Basicamente é isso. E um dos campos seria preenchido com o valor  de horas da carga horária desse funcionário no intervalo escolhido pelo usuário.

 

Explicando de novo: Eu tenho uma referência de tempo fixa, escolhida pelo usuário que emitiria o relatório. A partir daí eu tenho um intervalo que será considerado, intervalo esse que será calculado a partir do período que é a carga horaria do funcionário. Ufa! Acho que deu pra entender.

Listagem 1.

Kent Back, fala sobre bad smells no seu código referindo a qualquer perda de legibilidade e design no seu código. De cara podemos citar vários. Listaremos alguns mais relevantes. E no próximo tópico, citarei práticas para corrigir esses “fedores”.

Eu lembro que quando revisaram esse código, eu ouvi “nossa mãe do céu!”. Pensei então: “a casa caiu”. E realmente esse não foi uma das minhas melhores performances.

Tá, mas o que diabos é essa cascata de ifs? Somente esse erro, ja desencadeia várias más praticas(e essa ganha de goleada.).  Com isso, vemos a lógica replicada 7 vezes , uma para cada caso que a carga horaria se encaixa no período referencia. Vemos a padronização dos parâmetros em que cada método recebe. São exatamente os mesmos, mudando apenas o comportamento interno entre eles.

Com isso temos um método com um tamanho grande, e na listagem 2, vemos a implementação dos 7 métodos, responsáveis pelos cálculos. E na listagem 3, vemos os métodos verificadores na classe CargaHoraria.java. Da mesma forma, também replicados. Juntando métodos replicados, com um método central que invoca os demais, temos como um resultado uma classe quilométrica. E quem gosta de manter uma classe desse tipo? Imagine que o cálculo precisa de uma pequena modificação. Pois é, temos que corrigir os 7 métodos.

Listagem 2

Dando continuidade, o Guilherme Silveira diz na sua palestra sobre Design de Código, que qualquer código que não caiba na resolução normal do monitor não merece respeito. E exatamente isso acontece, vemos nomes de métodos talvez explicativos até demais, tornando excessivamente extenso. Esses erros ocorrem na listagem 1 e 2.  Como por exemplo o método  DataUtil.getQuantidadeVezesOsDiasDaSemanaApareceramNoPeriodo(produtividadeDTO.getDtInicial(), produtividadeDTO.getDtFinal(), parseList(cargaHoraria, diasList)).doubleValue();

Listagem 3

Aqui merece um sono WTF! Que o Martin cita no inicio do livro clean code. E além de tudo, o método doubleValue() ainda é chamado pra tornar ainda mais feio. Mas calma, posteriormente mostrarei soluções.

II) Testes Automatizados: Já escrevi uma série de posts sobre testes(links), e pela web está repleta de material sobre o assunto. Então, qual garantia que eu tenho de alterar meu código, e ao final da refatoração ele está ainda fazendo o que eu acho que ele deve fazer? Testes baby! Abuse dos testes e verifique se o código que irá ser refatorado possui testes cobrindo as funcionalidades.

III) E então eu preciso adicionar uma funcionalidade nova. Ai que está o problema. Como eu vou fazer isso? Para garantir faça TDD. A Web também está repleta de material sobre o assunto. Pelo menos para você ganhar embasamento teórico. Pois, da teoria para a prática a distância é muito grande. E para você ter um aproveitamento maior, faça Pair Programming, prática do XP.  Foi a partir de um PP que a idéia desse post saiu. E minha maior sorte o me pair era bem mais experiente que eu, então o aprendizado foi muito grande. Recomendo essa técnica.

IV) Fica para o próximo post, onde apontarei soluções.

Link para a parte 1.

REFACTORING – Caso Real e boas maneiras Parte I (Intro)

1)        INTRO

A Engenharia de Software tradicional, ou pelo menos eu a chamo assim(aquela em que eu dormi muito nas aulas da faculdade), possui toda a uma divisão impecável de processos de software, quase todos aparentado uma linha de montagem do século XIX. Sendo alguns modelos mais conhecidos do que outros. Citando o modelo waterfall, vemos bem evidente a linha de montagem. Cada etapa do modelo, projeto, desenvolvimento, testes, etc. Ocorria ao término da anterior, sempre ocorrendo essa dependência.

Pois bem, os tempos mudaram, e com eles as novas metodologias de desenvolvimento de software despontaram no mercado.  Com todo “jeitão” interativo-incremental de ser. Afim de combater os modelos engessados citados anteriormente.

Mas o post não tem como objetivo discutir as vantagens de uma ou de outra, desvantagens e assim por diante.  Muito menos ter aquelas discussões filosóficas (métodos ágeis #win e pronto! 😀 ). E sim trazer uma preocupação que com o advento desses novos métodos fica muito mais evidente, que é a manutenção do código.

Não temos mais etapas bem definidas no desenvolvimento, muito menos naquele ciclo de vida do software. Aquele que diz que 70% do tempo de vida do seu software irá ser dedicado a manutenção.  Óbvio que não faço idéia de porcentagem exata. Mas veja bem, a cada momento que você revisa um código, feito por você ou não, a qualquer momento e em qualquer Sprint, mil perdãos amigos, mas vocês estão dando manutenção. E com essa tarefa cada vez mais em evidência, vemos a importância de tratarmos bem esse código, afinal de contas será você, seu colega de trabalho ou algum conhecido que irá encará-lo posteriormente e NÃO um  DAMMIT FREAK  COMPUTER .

Faremos algumas técnicas de Refactoring, em um código ruim(feito por mim), identificaremos “bad smells” e corrigiremos passo a passo, seguindo duas principais fontes. Refactoring – Improving The Design Of Existing Code, Martin Fowler e Clean Code: A Handbook of Agile Software Craftsmanship, Robert Martin.

E claro agradecer meu amigo @marceloemanoel, que sem ele, esse post não sairia.

 

2)         Refactoring

O termo refactoring possui muitas definições. Mas segundo Martin Fowler: Refatoração é uma mudança feita na estrutura interna do software para torná-lo mais fácil de entender e mais barato realizar qualquer mudança sem modificar o comportamento externo do sistema. Além de ser uma fonte chave no post, achei essa a melhor definição.  Bem ao final do post desejo ter demonstrado algumas práticas.

2.1) Porque refatorar?

Para responder essa perguntar vou ser bastante sucinto.  Você refatorando, seu código irá ter um ganho no design. Tendo um melhor design, o código fica mais fácil de ser entendido por GENTE. Sendo mais fácil de ser entendido, os bugs serão mais difíceis de aparecer, e os que já estão “perturbando”, serão achados mais facilmente.

Enfim, citei só o caminho feliz, pois eu creio que essa prática vale realmente a pena. Mas é necessário experiência e conhecimentos principalmente em Orientação a Objeto para chegar a um bom “Refactorer” J.

2.2) Quando refatorar?

Basicamente, sempre que o valor estético do seu código estiver em déficit, prejudicando a clareza e a comunicação.

Mas citando alguns casos aparecem em comum em ambos autores:

  • Código duplicado (duplicated code)
  • Método longo (long method)
  • Classe grande (large class)
  • Lista de parâmetros longa (long parameter list)
  • Má indentação(Bad Indentation)

Para mais detalhes, http://sourcemaking.com/refactoring possui uma síntese dos casos de refatoração extraídos do livro do Fowler.

Próxima etapa, colocaremos a mão na massa, veremos o código problemático e apontaremos os bad smells mais evidentes.

ANDROID: SINCRONIZANDO COM A WEB

Neste Post veremos como sua app android pode se comunicar e obter dados a partir de  algum servidor web.

Essa comunicação é feita utilizando JSON (JavaScript Object Notation), que é uma formatação leve de troca de dados e de fácil manipulação de dados formatados de sua maneira.

Nesse exemplo, que é apenas a captura de um arquivo json retornada pelo servidor, utilizaremos a classe HttpClient para abrir a comunicação. Vamos abrir uma InputStream e com a classe Scanner , receber os dados enviados do servidor e concatenar em uma StringBuffer. Exemplo do método bastante simples “carregaJsonDoServidor” a seguir:


public String carregaJsonDoServidor() throws ClientProtocolException, IOException {

     HttpClient httpClient = new DefaultHttpClient();

     HttpGet httpGet = new HttpGet(encode);

     HttpResponse response = httpClient.execute(httpGet);
     StringBuffer sb = new StringBuffer();

     HttpEntity entity = response.getEntity();

     if (entity != null) {

           Scanner s = new Scanner(entity.getContent());

           s.useDelimiter(",");

           while (s.hasNext()) {

                  sb.append(s.next()).append(",");

            }

      }

      return sb.toString();

}

A Magia dos Testes Automatizados.

A parte final dos três posts falando sobre testes. Vamos ver uma poderosa ferramenta de automação que é o Apache Ant.

O ANT trabalha através de tarefas, que são especificadas através de um arquivo XML chamado buildfile, onde ao editamos este arquivos definindo as tarefas que desejamos que ele faça, como por exemplo:

Criarmos pastas no sistema operacional, pastas que poderemos usar por exemplo para colocar os executáveis da aplicação que estamos desenvolvendo;

Compilarmos recursivamente todos os fontes na pasta dos arquivos fontes de nosso projeto, colocando na pasta dos executáveis;

Copiarmos arquivos, deletarmos arquivos, listarmos arquivos;

Fazer conexões com bancos de dados, utilizarmos comandos do sistema, fazer log de nossos projetos, dentre várias outras tarefas.

O que demonstrarei é como o Ant automatiza tarefas necessárias para que sua aplicação esteja pronta para a implantação, distribuição, etc. Nesse post, abordaremos as seguintes tarefas a serem executadas:

  • Deleção e criação de diretórios.

  • Definir as libs que serão incluídas no projeto.

  • Compilar suas classes.

  • Definir seus testes e executá-los.

  • E o objetivo final, que é gerar o arquivo .war.

Aproveitando a estrutura do projeto já desenvolvido nos outros posts, <link aqui referenciando os posts antigos>vamos criar o arquivo build.xml na raiz do projeto. A estrutura do arquivo xml segue uma estrutura uniforme, mais ou menos dessa forma:

<project name="nome_projeto" basedir="." default="alvo1">

        <target name="alvo1">

             <tarefa1 />

             <tarefa2 />

        </target>

        <target name="alvo2">

              <tarefa1 />

              <tarefa2 />

        </target>

        <target name="alvo3">

              <tarefa1 />

        </target>
</project>
A raiz do arquivo é o elemento project, que possui os atributos name(nome do projeto, ah vá..),basedir(O diretório base a partir do qual os demais caminhos para arquivos e diretórios serão calculados. O “.” se refere ao diretório atual), default(Se você executar o Ant via Terminal e não for especificado nenhum alvo, o alvo declarado aqui será executado).

Os elementos filhos, que são os target, e neles podem possuir uma ou mais tarefas(tasks) a serem executadas (novamente – criar, renomear ou excluir diretórios, compilar e empacotar arquivos, etc. ).

Pois bem, vamos ao “jeitão” do nosso XML. Vamos listar as tarefas que serão executadas e algumas particularidades:

1.Declaro meu classpath (as libs que serão utilizadas no meu projeto).
<path id="classpath">
        <pathelement location="${classes.dir}" />
        <fileset dir="${lib.root}">
              <include name="*.jar" />
        </fileset>
</path>
2.Target, ele exclui o diretório que é criado pelo ant (target). E serão recriados os diretorios onde serão armazenados as classes compiladas e os testes compilados, respectivamente.
<target name="clean">
      <delete dir="${target.dir}"/>
      <mkdir dir="${classes.dir}"/>
      <mkdir dir="${test.classes.dir}"/>
</target>
3. Target, as classes e os testes serão compilados e “jogados” para seus respectivos diretórios, que foram criados no target anterior.
<target name="compile" depends="clean">
        <javac srcdir="${basedir}" destdir="${classes.dir}" >
         <classpath>
            <path refid="classpath"/>
         </classpath>
        </javac>
     <!-- Compila Test classes -->
        <javac destdir="${test.classes.dir}" srcdir="${test.source.dir}">
      <classpath>
              <path refid="classpath"/>
      </classpath>
        </javac>
</target>
4.Próximo target, onde será executado os testes. O Ant gerará um relatório, no formato que você definir na tag “formatter”, armazenando em algum diretório de sua preferência. Adicionamos o classpath novamente e definimos o batchtest (no qual todas as classes com o padrão **/**Teste.java, serão reconhecidas como classe de teste e executadas como tal).
<target name="teste" depends="test-mysql">
        <mkdir dir="${test.report.dir}"/>
        <junit printsummary="on" fork="no" haltonfailure="true" haltonerror="true">
              <sysproperty key="basedir" value="." />
              <formatter type="xml" />
              <classpath refid="classpath"/>
              <batchtest todir="${test.report.dir}">
                    <!-- Unit Tests -->
                    <fileset dir="${test.source.dir}/unit">
                           <include name="${test.source.dir}/unit/${test.pattern}" />
                    </fileset>
                    <!-- Integration Tests -->
                    <fileset dir="${test.source.dir}/integration">
                           <include name="${test.source.dir}/integration/${test.pattern}" />
                    </fileset></p>

              </batchtest>
       </junit>
</target>
5.Por fim, se todas as etapas forem construídas sem erros e os testes passarem, então criaremos o arquivo .war para realizar o deploy no servidor.
<target name="buildwar" depends="teste">
         <javac srcdir="${basedir}" destdir="${classes.dir}">
               <classpath refid="classpath"/>
         </javac>

         <mkdir dir="${war.dir}" />
         <war destfile="${war.dir}/VRaptorTestesAutomatizados.war" webxml="${web.xml}">
              <classes dir="${classes.dir}" />
              <lib dir="${lib.root}"></lib>
              <fileset dir="WebRoot/">
                   <include name="META-INF/**"/>
                   <include name="*.jsp" />
                   <include name="*.html" />
              </fileset>
         </war>
</target>
*Todos os caminhos ${alguma-coisa} está definido no arquivo build.properties, definido na segunda linha.
Rodando o seu script Buildfile, vamos ao resultado no console:
E ao final, como prova que realmente você fez o que tinha que fazer :). Fiz o deploy no servidor e vamos ao resultado no browser.
Sinal que sua aplicação deu certo. Compilamos nossas classes, fazemos nossos testes e geramos nosso .war. Isso é só um pouco que essa poderosa ferramenta, que é o Ant pode fazer. Até os próximos posts.

DESENVOLVENDO PARA ANDROID: MEXENDO COM MAPAS

Opa, voltando a falar sobre Android, vamos falar de um negócio bacana, que é brincar com o GMap.

Mas para manipularmos mapas, teremos que ter uma Google API Key . Para consegui-la, entre no link. Nele, você deve colocar seu fingerprint, que pode ser conseguido através do comando:

keytool -list -alias meualias -keystore minhachave.jks

o google vai ti devolver uma tela aonde você terá um trecho de código que será usado na sua view de mapas.


<com.google.android.maps.MapView

     android:layout_width="fill_parent"

     android:layout_height="fill_parent"

     android:apiKey="0BN1gWBPEYDQluZey4KPKZH_C4AMH2sG02G1GLg"

     android:id="@+id/map_view"/>

Vamos ao momento feliz, mão na massa!!

O desafio será o seguinte: Me achar no mapa. Mostrando a minha localização pelo gps.

I) Temos que criar uma o mapa.xml dentro do res/layout, uma vez que recebemos o código do site do google que exibi acima.


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="fill_parent"

          android:layout_height="fill_parent">

          <com.google.android.maps.MapView

               android:layout_width="fill_parent"

               android:layout_height="fill_parent"

               android:apiKey="0BN1gWBPEYDQluZey4KPKZH_C4AMH2sG02G1GLg"

               android:id="@+id/map_view"/>

</LinearLayout>

II) Como já foi visto , uma tela é uma Activity. Mas neste caso será um MapActivity pois queremos todas as funcionalidades que um mapa pode nos dar. Vamos criar uma classe Mapa.java que extenda MapActivity:


@Override

protected boolean isRouteDisplayed() {

     return false;

}

@Override

protected void onCreate(Bundle icicle) {

        super.onCreate(icicle);

        setContentView(R.layout.mapa);

        mapView = (MapView) findViewById(R.id.map_view);

        mapController = mapView.getController();

        //Pegamos os controles necessários do nosso sistema.

        mapView.setSatellite(true);

        mapView.setStreetView(true);

        mapView.displayZoomControls(true);

        mapController.setZoom(14);

        final List<Overlay> overlays = mapView.getOverlays();

        //Criamos um overlay, assim podemos nos achar no mapa e ainda mostrar o recurso de bússola(plus!).

        MyLocationOverlay myLocationOverlay = new MyLocationOverlay(this, mapView);

        overlays.add(myLocationOverlay);

        myLocationOverlay.enableCompass();

        myLocationOverlay.enableMyLocation();

        //E temos que atualizar o nosso sistema, quando tivermos em movimento. Para isso, criamos um listener, e //antes temos que inicializar o GPS para que possa escolher o melhor serviço de posicionamento disponível.

        LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        Criteria criteria = new Criteria();

        criteria.setAccuracy(Criteria.ACCURACY_COARSE);

        criteria.setAltitudeRequired(false);

        criteria.setCostAllowed(true);

        criteria.setPowerRequirement(Criteria.POWER_HIGH);

        String provider = locationManager.getBestProvider(criteria, true);

        Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);

        atualizarMeuLocal(location);

}

        LocationListener locationListener = new LocationListener() {

              public void onStatusChanged(String provider, int status, Bundle extras) {

              }

              public void onProviderEnabled(String provider) {

              }

              public void onProviderDisabled(String provider) {

                   atualizarMeuLocal(null);

              }

              public void onLocationChanged(Location location) {

                    atualizarMeuLocal(location);

               }

         };

              //Socilitamos que rode o listener a cada 2 segundos ou uma diferença de 20 metros.

               locationManager.requestLocationUpdates(provider, 2000, 20, locationListener );

   }

          //Agora temos que criar o nosso método atualizarMeuLocal(Location location), repare que ele o location que //usará para localizar o seviço e buscar a posição.

          private void atualizarMeuLocal(Location location) {

                if(location != null){

                     Double geoLat = location.getLatitude() * 1E6;

                     Double geoLong = location.getLongitude() * 1E6;

                     GeoPoint point = new GeoPoint(geoLat.intValue(), geoLong.intValue());

                     //Sempre que o o método for chamado, ele irá mover o nosso mapa para a posição atual.

                     mapController.animateTo(point);

                 }

            }

Testes de Integração: Validando ainda mais sua aplicação

A próxima etapa nos artigos sobre teste. Vamos aos chamados Testes de Integração. Como tradição, vamos a “definição wiki de ser”. “teste de integração é a fase do teste de software em que módulos são combinados e testados em grupo.”.

Bem, não é a definição mais clara que podemos encontrar. Mas calma, vejamos desse jeito:

Nos testes unitários, cada módulo do sistema será testado individualmente. Sem influência de outras classes do sistema e se possuir alguma dependência, nós criamos Mocks que simulem o funcionamento dessa dependência.

Nos testes de integração, nós queremos que os módulos sejam testados de forma que interajam com o restante do sistema, oferecendo dependências reais para garantir que elas funcionem em conjunto.

Imagine a situação de um cadastro (aquele crud “basicão”). Com o Teste de Unidade, você cria um teste para as regras de negócios, outro para as classes de persistência com o banco e assim por diante. Nos Testes de Integração, você testa somente o método Inserir, ou Pesquisar ou Atualizar e deixa que os módulos si relacionem de verdade, sem Mock Objects, sem nenhum artifício qualquer.

Para realizar nossos testes, novamente utilizaremos o JUnit,  Spring Framework, e o DBUnit, que é uma extensão do JUnit que oferece funcionalidades específicas para testes envolvendo banco de dados.

Primeiramente você pode encontrar uma melhor explicação sobre o DBUnit aqui. O DBUnit necessita de um arquivo xml que funcionará como o conjunto dos dados que serão inseridos no banco antes dos testes rodarem, afim de garantir que os dados que serão usados estarão presentes no banco. Tomamos o exemplo da tabela Filme, com os campos, codigo, titulo e ano.

<dataset>

 <filme codigo="10" titulo="HANNIBAL" ano="2002"/>
 <filme codigo="20" titulo="RED DRAGON" ano="2003"/>
 <filme codigo="30" titulo="ADVOGADO DO DIABO" ano="1997"/>
 <filme codigo="35" titulo="PERFUME DE MULHER" ano="1991"/>
 <filme codigo="40" titulo="THE GODFATHER" ano="1970"/>

</dataset>]
Mas antes de implementar-mos nossos testes, precisamos configurar o dataSource e adicionar o dbUnit no Spring.
<context:component-scan base-package="com.wordpress.yuriadamsmaia.integration.base.dbunit"/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.SingleConnectionDataSource" >

<property name="driverClassName" value="com.mysql.jdbc.Driver" />
 <property name="url" value="suaURL" />
 <property name="username" value="SEUUSERNAME" />
 <property name="password" value="SUAPASSWORD" />
 <property name="suppressClose" value="true" />
 </bean>
Antes de escrever os testes, vamos conhecer o que iremos testar. Para não estender muito, iremos limitar a testar um único método(no caso o método pesquisar).  *
@Service("filmeService")
public class FilmeServiceImpl implements FilmeService{
 @PersistenceContext
 private EntityManager entityManager;
 private Session getSession() {
 return ((Session) entityManager.getDelegate());
 }
@SuppressWarnings("unchecked")
@Override
public List<Filme> pesquisar(Filme filme) {
Criteria criteria = getSession().createCriteria(Filme.class);

criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

if (!StringUtils.isEmpty(filme.getTitulo()))
criteria.add(Restrictions.like("titulo", "%" + filme.getTitulo() + "%"));
if (!StringUtils.isEmpty(filme.getAno()))</p>
criteria.add(Restrictions.like("ano", "%" + filme.getAno() + "%"));

criteria.addOrder(Order.asc("codigo"));
return criteria.list();
}

}
* Estamos utilizando o hibernate e JPA API para  a persistência. Então toda configuração no Spring para permitir essa integração será disponivel no final do post.

Escrevendo nosso teste:

O teste terá os seguintes passos:
  1. Limpar e Carregar os dados antes para nossos métodos de teste;
  2. Realizar os métodos de teste, onde nós iremos comparar se o valor está conforme o arquivo XML.
A classe FilmeServiceImplTeste.java
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
 "file:./WebRoot/WEB-INF/config/spring/applicationContext.xml",
 "file:./WebRoot/WEB-INF/config/spring/applicationContext-persistence-test.xml"
})
public class FilmeServiceImplTeste {
private static final String DATASET = "./test/com/wordpress/yuriadamsmaia/integration/base/dbunit/xml/FilmeServiceImplTeste.xml";
@Autowired DbUnitManager dbUnitManager;
@Autowired FilmeService filmeService;

 @Before
 public void setUp() {
 dbUnitManager.cleanAndInsert(DATASET);
 }
Anotamos a classe com @RunWith(SpringJUnit4ClassRunner.class) para o JUnit rodar os testes com o Spring Test. E também anotamos a classe com o @ContextConfiguration(locations={“file:./WebRoot/WEB-INF/config/spring/applicationContext.xml”, “file:./WebRoot/WEB-INF/config/spring/applicationContext-persistence-test.xml”}), que define os nossos arquivos XML onde estão as configurações, com o detalhe que criamos um outro XML(applicationContext-persistence-test.xml) somente para os testes.
O método cleanAndInsert(DATASET) da Interface DbUnitManager que está sendo injetada, faz com que sempre quando o teste é iniciado,  base de dados é limpa e os dados são re-inseridos(evitando duplicata de dados, ou seja, lixo).
public void cleanAndInsert(String dbUnitXmlPath) {

try {
 IDatabaseConnection dbconn = this.getDbUnitConnection();
 DatabaseOperation.CLEAN_INSERT.execute(dbconn, this.getDataSetFrom(dbUnitXmlPath));
 dbconn.close();
 } catch (Exception e) {
 e.printStackTrace();
 throw new RuntimeException(e);
 }
 }
private IDatabaseConnection getDbUnitConnection() throws      DatabaseUnitException, SQLException {
IDatabaseConnection dbconn = new DatabaseConnection(this.getConnection());
dbconn.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYP E_FACTORY, new MySqlDataTypeFactory());
return dbconn;

}
 private IDataSet getDataSetFrom(String dbUnitXmlPath) throws IOException,
 DataSetException, FileNotFoundException {
 return new FlatXmlDataSetBuilder().build(new FileInputStream(dbUnitXmlPath));
 }
Agora os testes. Daqui pra frente , o raciocínio não muda dos testes unitários.
@Test
 public void deveriaPesquisarFilmesSemCamposEspecificados(){
 Filme filme = new Filme();
 List<Filme> pesquisa = filmeService.pesquisar(filme);
 verificaListaRetornoPesquisa(pesquisa);
 assertEquals("deveria estar trazendo a lista de tamanho correto", pesquisa.size(), LISTA_TAMANHO);
 }
private void verificaListaRetornoPesquisa(List<Filme> pesquisa) {</p>
assertNotNull("nao deveria ser nula", pesquisa);</p>
assertFalse("nao deveria retornar a lista vazia", pesquisa.isEmpty());</p>
assertEquals("deveria estar trazendo a lista correta", pesquisa.get(0).getTitulo(), FILME_TITULO);</p>
assertEquals("deveria estar trazendo a lista correta", pesquisa.get(0).getAno(), FILME_ANO);</p>

}

De fato, como estou passando como argumento do pesquisar um objeto filme com todos os campos vazios, o método retorna todos os registros na tabela. Fazemos as verificações, se a lista retornada não é nula, não é vazia, verificamos se o primeiro elemento da lista retornada está de acordo com o arquivo xml. E finalmente verificamos o tamanho da lista, a fim de saber se todos os elementos foram pesquisados.

De forma análoga, podemos realizar uma pesquisa limitada por algum campo, por exemplo o título.

@Test
public void deveriaPesquisarFilmesPeloTitulo(){
 Filme filme = new Filme();
 filme.setTitulo(FILME_TITULO);
 List<Filme> pesquisa = filmeService.pesquisar(filme);
 verificaListaRetornoPesquisaPeloTitulo(pesquisa);
}
private void verificaListaRetornoPesquisaPeloTitulo(List<Filme> pesquisa) {
 assertNotNull("nao deveria ser nula", pesquisa);
 assertFalse("nao deveria retornar a lista vazia", pesquisa.isEmpty());
 assertEquals("deveria estar trazendo a lista correta", pesquisa.get(0).getTitulo(), FILME_TITULO);
}
Espero ter passado o conhecimento que tenho adquirido nas ultimas semanas sobre Testes. O projeto vai estar disponível no github para download. E o próximo passo será automatizá-los, via Apache Ant.
link para download: https://github.com/yuriadams/VRaptorTestesAutomatizados

Com VRaptor e Mockito é muito mais fácil testar!

E ai negada, depois de um tempão sem postar nada(Faculdade e o novo estágio agradecem), estou de volta para falar um pouco sobre um assunto que tenho dando bastante  ênfase que são os testes. Pretendo escrever dois artigos falando sobre tal. O primeiro a seguir abordando os testes de unidade e o próximo a respeito dos testes de integração. Então vamos lá.

           “Usando TDD, quando acabamos, realmente acabamos. Ou seja, dificilmente temos que retornar ao código futuramente para corrigir falhas, pois possíveis falhas já foram detectadas e corrigidas durante a confecção dos testes.”
Com essa citação que pode ser encontrada no site da ImproveIt, damos início a um dos temas “quentes” do momento que são os testes. Mas o que é esse TDD?Bem, TDD (Test Driven Development) é uma das práticas abordadas na metodologia XP, que se baseia em escrever os testes antes de programarmos o código-fonte. Legal essa idéia do TDD, mas o post irá focar nos testes, especificamente nos testes de unidade ou testes unitários. Então XP fica para a próxima.
O teste unitário ou de unidade é uma modalidade de testes que se concentra na verificação da menor unidade de código funcional do projeto de software. Como estamos no mundo OO, essa menor unidade pode ser entendida a um objeto ou mesmo a um comportamento do mesmo, reagindo a um estimulo (métodos da classe). Com entradas que são parâmetros e as saídas são o valores de retorno, exceções ou o estado do objeto.
O que será demonstrado nesse post, será desde uma explicação de testes, com exemplos simples sobre testes unitários. Até aprofundarmos mais, mostrando testes em uma classe de controle do VRaptor, passando pelo conceito de Mock Object, abordando as facilidades que  VRaptor traz, afim de “Mockar” os objetos do framework.
Para implementar os testes usaremos o bastante conhecido JUnit, ele escreve testes em Java e se integra facilmente com qualquer IDE (Eclipse, NetBeans, whatever).
              Vamos a uma classe simples de teste do JUnit:
public class MathTeste {

@Test

public void somaTeste(){

        Assert.assertEquals(9, 5+4);

}

}

A primeira vista:
1. Nós dizemos ao Junit que aquele método é um teste pela annotation @Test.
2. Eu quero saber se o resultado 5+4 é IGUAL a 9(dã!!), daí o assertEquals. Não para por ai, a <a href=”http://junit.sourceforge.net/javadoc/org/junit/Assert.html”>classe Assert</a> possui inúmeros métodos de verificação.

E ao rodar o teste, o plugin do Junit na IDE(Eclipse no caso), “cospe” o resultado. Trata de um sinal verde, se seu teste passou. Vermelho se não passou (legal né?).

Ok. Passando a parte introdutória, vamos ao VRaptor. O VRaptor é um framework MVC em Java focado no desenvolvimento rápido e simples, e na fácil manutenção do código. Mais uma definição wiki.</div>
Beleza, mas nosso foco ainda não é entrar em detalhes sobre o VRaptor e como ele trabalha, mas sim TESTES. Assim vou mostrar a nossa classe de controller a ser testada(Limitaremos somente a funcionalidade de pesquisa).</div>

@Resource
public class FilmeController {

      private final Result result;
      private FilmeService filmeService;
      private Validator validator;

      public FilmeController(Result result, FilmeService filmeService, Validator validator) {
              this.result = result;
              this.filmeService = filmeService;
              this.validator = validator;
      }

      @Path("/filme")
      public void index(){
      }

      @Get
      @Path("/filme/pesquisa")
      public void pesquisa(Filme filme){
           List loadFilme = null;
           try{
                loadFilme = filmeService.pesquisar(filme);
                if(loadFilme.isEmpty()){
                      result.include("notice", "Nenhum produto encontrado!!");
                }
                result.include("filmes", loadFilme);
                result.forwardTo(this).index();
          }catch(Exception e){
                result.include("erros", e.getMessage());
          }
      }
            Show galera. Classe controller mostrada, agora vamos ao FilmeControllerTeste.java, nossa classe que realizará o teste unitário do FilmeController.java.
private Result result;
private Validator validator;
private FilmeController filmeController;

@Mock private FilmeService filmeService;
            Criamos esses objetos para simular o comportamento da classe a ser testada. Uma breve explicação.  Result, que é um componente do VRaptor que consegue mudar o resultado do seu método. Similar a classe HttpRequest da Api Servlet. A Interface Validator, que é passada como parâmetro no construtor da classe, oferece meios para realizar validações no seu controller.
             E esse Mock. “WTF” Mock?
Mock objects são objetos que simulam o comportamento de objetos reais. Mas pra que isso? Serve para prender o escopo dos seus testes. Por exemplo, se você esta fazendo um teste em uma classe de controle e o método desta classe invoca um método de uma classe de serviço que faz uma consulta no banco, você deve usar um Mock para simular o objeto desta outra classe, simulando assim esta consulta, pois a consulta será testada no momento em que o teste para o seu método for criado.

             Antes de implementar o primeiro teste, vamos inicializar.. é.. o que precisamos pra começar os testes(A annotation @Before  do JUnit é utilizada justamente para isso).

  • Todos os Mocks (utilizando o Mockito API, para trabalhar com os mocks).
  • Result e Validator(Vraptor já disponibiliza os mocks para esses objetos).
</pre>
@Before
public void setUp(){
      MockitoAnnotations.initMocks(this);
      result = new MockResult();
      validator = new MockValidator();
      filmeController = new FilmeController(result, filmeService, validator);
}

               E finalmente vamos começar a brincadeira. Primeiro vamos ao “happy day”, o que deve acontecer se a pesquisa for bem sucedida.

//obs: Fazemos os imports estásticos afim de melhorar a leitura do código:
// import static org.junit.Assert.*;
// import static org.mockito.Mockito.*;
// import static org.mockito.Matchers.any;

@Test
public void deveriaPesquisarFilmes(){
        when(filmeService.pesquisar(any(Filme.class))).thenReturn(new ArrayList());
        filmeController.pesquisa(any(Filme.class));

        assertTrue("deve haver uma lista de Filmes", result.included().containsKey("filmes"));
        assertFalse("n‹o deve exibir nenhuma msg de erro)", result.included().containsKey("erros"));
}
              Teste passando, vamos aos porquês. A Api Mockito eh bem intuitiva, ela possui  métodos estáticos de fácil entendimento, senão vejamos.  “Quando(when) um filmeService pesquisar (filmeService.pesquisar(…)) qualquer filme (any(Filme.class)), então me retorne uma lista de filmes (thenReturn(new ArrayList<Filme>());). Mais intuitivo que isso impossível. Importante é você entender a semântica(feeling) da coisa e saber(no sangue) o comportamento da sua classe. O resto é detalhe de sintaxe.”
Vamos ao revés.
</pre>
@Test
public void deveriaTratarORetornoDeUmaListaNull(){
      when(filmeService.pesquisar(any(Filme.class))).thenReturn(null);
      filmeController.pesquisa(any(Filme.class));

      assertTrue("deve exibir uma mensagem de erro", result.included().containsKey("erros"));
      assertFalse("n‹o deve exibir nenhuma msg de aviso)", result.included().containsKey("notice"));
      assertFalse("nao deve haver uma lista de Filmes", result.included().containsKey("Filmes"));
}
             Testando o que pode acontecer se o método não for bem sucedido, alguma exceção lançada, ou seja algo dando errado, é o ponto chave dos testes. Você prever o que pode dar errado no seu código(aqui estou verificando um único problema que possa ocorrer, por questão de não me estender ainda mais) e na mesma hora tratar e corrigir esse erros, vão lhe poupar tempo depois que seu sistema estiver em produção. Afinal, time is money. Não estou afirmando que com os testes, você estará segurado 100% de erros, mas certamente eles demorarão mais a ocorrer e a manutenção se tornará menos dolorosa. Sem falar na melhoria do design do seu código com o uso de testes(principalmente se você estiver usando TDD – Leia Clean Code!).
REFERÊNCIAS:
O código completo pode ser baixado no meu github: http://www.github.com/yuriadams.