tag:blogger.com,1999:blog-25769600882850572642024-03-19T10:09:26.111-03:00Artesanato de SoftwarePara apaixonados por desenvolvimento de software...Anonymoushttp://www.blogger.com/profile/04313516968970529920noreply@blogger.comBlogger11125tag:blogger.com,1999:blog-2576960088285057264.post-14654275428399336052013-08-30T10:27:00.001-03:002013-08-30T11:11:28.479-03:00Programação funcional para programadores JavaEm um post anterior comecei uma série sobre Scala, focando em programadores Java. Porém notei que a curva de aprendizado de uma linguagem, principalmente em novo paradigma pode ser drástica demais. Portanto decidi focar mais no aprendizado do paradigma aproveitando o que puder do Java. Apesar de Java não ser funcional podemos aprender algumas técnicas interessantes e melhorar nossos projetos atuais.<br />
<br />
Uma característica importante do paradigma funcional é o projeto dos tipos das linguagens. O uso de tipos como listas, mapas, árvores e conjuntos são enfatizados para a manipulação de dados. Nas linguagens mais puras os valores são imutáveis, logo as variáveis devem ser inicializadas com valores válidos. <b>Note que isto é muito importante</b>. Se precisamos inicializar nossas variáveis com valores válidos isso significa que nunca teremos variáveis nulas. O próprio <a href="http://en.wikipedia.org/wiki/Tony_Hoare" target="_blank">inventor</a> do conceito de nulo reconhece que isso é um erro.<br />
<br />
Caso ainda esteja resistente a reconhecer este erro, lembre-se de quantas NullPointerException seu código de produção gerou, ou ao menos quanta complexidade foi adicionada ao código através de condicionais você teve de fazer verificando se algo é diferente de null.<br />
<br />
Claro que podemos apelar para o <a href="http://en.wikipedia.org/wiki/Null_Object_pattern" target="_blank">Null Object Pattern</a>, mas nem sempre é trivial e envolve muito trabalho em alguns casos.<br />
<br />
O ideal seria o sistema de tipos da nossa linguagem nos ajudar com isso. Vamos ver um exemplo:<br />
<br />
<script src="https://gist.github.com/renanreismartins/6389666.js"></script>
Option é uma classe abstrata que representa um tipo que pode ou não ter valor. Teremos mais duas subclasses, uma indicado a existência de valor e outro a ausência. O método hasValue() informará isso para nós através de sua implementação em cada subclasse. O método get() retornar o valor, caso este exista e por fim getOrElse(T alternative) retorna o valor da Option, caso este seja inexistente é retornada a alternativa passada como parâmetro. As coisas ficarão mais claras com a implementação das subclasses e uso.<br />
<br />
Vamos ao subtipo que indica existência de valor:<br />
<br />
<script src="https://gist.github.com/renanreismartins/6389672.js"></script>
Como Some representa a existencia de valor o método hasValue() sempre retorna true, o método get() o valor.<br />
<br />
Agora o subtipo que representa ausência de valor:<br />
<br />
<script src="https://gist.github.com/renanreismartins/6389681.js"></script>
Como None representa ausência de valor o método hasValue() sempre retornará falso, e lançaremos uma exceção caso seja tentado recuperar o valor que não existe. Já que None não possui valor, o método equals() sempre retorna true caso seja passada outra instância de None.<br />
<br />
Agora vamos fazer uso do nosso novo sistema de tipos:<br />
<br />
<script src="https://gist.github.com/renanreismartins/6384507.js"></script>
No código acima criamos 3 Options e iteramos sobre eles chamando o método getOrElse(T alternative), dessa forma, se existe um valor, o mesmo é retornado, caso contrário é retornado o valor alternativo.<br />
<br />
Também podemos voltar á abordagem mais clássica, perguntando se existe valor no Option:<br />
<br />
<script src="https://gist.github.com/renanreismartins/6384582.js"></script>
Chamamos o método hasValue para verificar se aquela Option possui um valor e então o usamos.<br />
<br />
Por fim, vamos ver como fica o código dos nossos métodos que podem retornar um valor ou ausência de valor e seu uso:<br />
<br />
<script src="https://gist.github.com/renanreismartins/6384684.js"></script>
Note que o grande ganho com essa abordagem é deixar explicito através de código que o valor que estamos usando é opcional, o retorno do método agora é um Option, bem mais legível e menos passível de erros, pois sendo um Option, devemos determinar se o Option é uma instância de Some antes de usar o valor.<br />
<br />
Desenvolvendo nossas próprias classes para melhorar o sistema de tipos nesse caso, parece overhead, uma solução é o uso do <a href="https://code.google.com/p/guava-libraries/" target="_blank">Guava</a>, uma lib que possui recursos interessantes que dão um "sabor"funcional para nossos projetos.<br />
<br />
<a href="http://hmkcode.com/google-guava-null/" target="_blank">Aqui</a> tem uma rápida introdução de como usar esses recursos com o Guava.Anonymoushttp://www.blogger.com/profile/04313516968970529920noreply@blogger.com0Porto Alegre - Rio Grande do Sul, Brazil-30.0277041 -51.228734599999996-30.4673011 -51.874181599999993 -29.588107100000002 -50.5832876tag:blogger.com,1999:blog-2576960088285057264.post-1103467194736697682013-08-12T20:03:00.000-03:002013-08-12T20:03:49.173-03:00Por que preciso declarar como final variáveis passadas à classes anônimas (inner class)?É muito comum quando estamos desenvolvendo interfaces gráficas seja em Swing ou Android o uso de classes anônimas, geralmente usamos classes anônimas como callbacks em listeners de eventos. Devido às características do Java, quando precisamos de um callback passamos uma instância de classe como parâmetro ao invés de simples funções como podemos fazer em Javascript por exemplo.<br />
<br />
<script src="https://gist.github.com/renanreismartins/6215073.js"></script>
Repare que no código acima temos um erro, pois tentamos acessar a variável <b>"content"</b> dentro de uma <a href="http://docs.oracle.com/javase/tutorial/java/javaOO/innerclasses.html" target="_blank">inner class</a>. Para resolver o problema é simples, basta declararmos <b>"content"</b> como <b>final</b>.<br />
<br />
<script src="https://gist.github.com/renanreismartins/6215187.js"></script>
Para entender porque devemos declarar variáveis a serem acessadas em inner classes como final, devemos primeiro entender como inner classes são traduzidas em byte code.<br />
<br />
Quando temos uma inner class ela não é gerada no mesmo arquivo de byte code da classe que a contém (outer class), são gerados dois arquivos, um com a outer class e outro com a inner class:<br />
<br />
Classe1.class<br />
Classe1$OnClickListener.class<br />
<br />
Aqui surge um problema, nossa classe Classe1$OnClickListener.class precisa acessar a variável <b>"content"</b> declarada em Classe1.class. Para que isso seja possível o compilador cria em Classe1$OnClickListener.class um atributo que recebe uma cópia do valor da variável da outer class. Mas imagine que por algum motivo a variável em Classe1.class ou mesmo o atributo em Classe1$OnClickListener.class tenha seu valor alterado, teriamos um problema de sincronização de dados. Para evitar este problema somos obrigados a declararmos as variáveis que serão usadas em inner classes como <b>final</b>, assim os valores tanto nas outer classes e inner classes serão iguais.<br />
<br />
Referências:<br />
<br />
<ul>
<li>http://stackoverflow.com/questions/7423028/java-local-variable-visibility-in-anonymous-inner-classes-why-is-final-keywo</li>
<li>http://techtracer.com/2008/04/14/mystery-of-accessibility-in-local-inner-classes/</li>
</ul>
<br />
<br />Anonymoushttp://www.blogger.com/profile/04313516968970529920noreply@blogger.com0tag:blogger.com,1999:blog-2576960088285057264.post-22535198291170684522013-04-05T16:43:00.000-03:002013-04-05T16:59:18.576-03:00Scala para programadores JavaVocê é um programador Java experiente, está sempre buscando conhecimento e novas formas de encontrar soluções. Uma forma de atingir este objetivo é aprender uma nova linguagem, preferencialmente com um paradigma diferente. Scala te chama atenção, por funcionar dentro da JVM, usar classes existentes do Java e por ser funcional, um paradigma que você ainda não conhece.<br />
<br />
Então caro leitor temos muito em comum, na saga de estudar a linguagem e também o paradigma funcional, tive a oportunidade de receber a ajuda de um <strike>hacker</strike> amigo, <a href="https://twitter.com/jonasabreu" target="_blank">@JonasAbreu</a>. O coach do Jonas está sendo fundamental. Fui à minha primeira reunião dos ScalaDores, o grupo é bem avançado, portanto se você conhece bem Scala será um prato cheio, se está iniciando, também não tem problema, você acaba tendo um bom aproveitamento.<br />
<br />
Uma grande questão é que você não gostaria de reaprender tudo que já sabe sobre programação, orientação a objetos e etc. Seria interessante se tivesse uma forma de aprender reaproveitando sua experiência, focando apenas nas novidades e de forma bem prática.<br />
<br />
Pensando nisso, começo a partir deste post, fazer uma série para programadores Java interessados em aprender Scala. Abordarei tudo de forma muito prática e bem baseada em coisas que acho importante ou código que usei para alguma solução, MUITO DO CÓDIGO SERÁ AUTO EXPLICATIVO. Explicarei a teoria e detalhes quando o código não for tão obvio assim.<br />
<br />
Para começar sugiro usar o interpretador de Scala no terminal. Instalar, iniciar o interpretador, tudo isso é bem fácil e já existe bons materiais, portanto não serão abordados aqui, ao menos nesse primeiro momento.<br />
<br />
Vamos começar!<br />
<div>
<br /></div>
<div>
<b>Variáveis</b></div>
<div>
Para declarar uma variável basta fazer:</div>
<div>
<br /></div>
<div>
var <i>nomeDaVariavel</i> = <i>valor</i></div>
<div>
<br /></div>
<div>
<script src="https://gist.github.com/renanreismartins/7cf4fe106c75411ffd4a.js"></script>
</div>
<div>
<br /></div>
<div>
Note que diferente do Java não precisamos declarar o tipo da variável, isso porquê Scala consegue, muitas vezes, inferir o tipo declarado. Mas caso quisermos declarar o tipo, por questões de legibilidade por exemplo, podemos fazer:</div>
<div>
<br /></div>
<div>
var <i>nomeDaVariavel</i> : <i>TipoDaVariavel</i> = <i>valor</i></div>
<div>
<br /></div>
<div>
<script src="https://gist.github.com/renanreismartins/fac310ab471ddaeef889.js"></script>
</div>
<div>
Também podemos criar uma variável "final" como em Java, para isso declaramos:</div>
<div>
<br /></div>
<div>
<script src="https://gist.github.com/renanreismartins/72803c9931786a4e7a23.js"></script>
</div>
<div>
Assim se você tentar atribuir um novo valor à variável idadeFinal receberá um erro:</div>
<div>
<br /></div>
<div>
error: reassignment to val</div>
<div>
<br /></div>
<div>
A variável "nome" é do tipo String, Scala não tem uma classe String então ela usa classe java.lang.String do Java. Já "idade" é do tipo Int (<a href="http://www.scala-lang.org/api/current/index.html#scala.Int" target="_blank">scala.Int</a>) que é correspondente ao tipo primitivo int, que temos no Java. Scala tem tipos correspondentes para os tipos primitivos do Java, por exemplo scala.Float para float, scala.Char para char. Quando seu código é compilado em bytecodes o compilador tenta usar os tipos primitivos do Java por questões de performance.<br />
<br />
<b>Funções</b><br />
Funções requerem uma atenção especial, pois podemos encontrar a mesma função declarada de várias formas, o que pode assustar de início, mas depois que aprendemos fica bem fácil.<br />
<br />
Para declarar uma função:<br />
<pre style="white-space: pre-wrap; word-wrap: break-word;">def <i>funcao</i>(<i>param</i> : <i>TipoParam</i>) : <i>TipoRetorno</i> = {
// corpo
}</pre>
<pre style="white-space: pre-wrap; word-wrap: break-word;"></pre>
<pre style="white-space: pre-wrap; word-wrap: break-word;"></pre>
Uma função que soma dois números:<br />
<br />
<script src="https://gist.github.com/renanreismartins/07fbf629acb13405916b.js"></script>
Temos sempre de declarar o tipo dos parâmetros, a função recebe dois parâmetros do tipo Int e retorna também um tipo Int. Note que após a declaração do tipo de retorno vem um sinal de igualdade "=" e então as chaves "{}" que é onde deve ficar o corpo do método.<br />
<br />
Em alguns casos* Scala consegue inferir o tipo do retorno da função, como é o nosso caso. Então podemos declarar a mesma função omitindo o tipo de retorno:<br />
<br />
<script src="https://gist.github.com/renanreismartins/7e59cfad4de745ed3115.js"></script>
Como nossa função possui apenas uma linha podemos também omitir as chaves:<br />
<br />
<script src="https://gist.github.com/renanreismartins/dd98c69ffd9099bb4b9a.js"></script>
* Se nossa função for recursiva temos de explicitar o tipo de retorno.<br />
<br />
Podemos declarar funções sem retorno também:<br />
<script src="https://gist.github.com/renanreismartins/29c55a170dcec34d45be.js"></script><br />
Neste caso Unit é o equivalente ao void do Java. Você pode omitir o retorno neste caso também:<br />
<script src="https://gist.github.com/renanreismartins/7960b06762002a24d706.js"></script><br />
<b>Um pouquinho de características funcionais</b><br />
Uma das principais características de linguagens funcionais é poder passar funções como parâmetros. Vamos a um exemplo bem prático disso, vamos criar uma classe Array e forneceremos uma maneira de executar um "processamento" em cada elemento do array.<br />
<br />
<script src="https://gist.github.com/renanreismartins/417cef3706e1f20180a6.js"></script>
Para isso precisamos definir nossa interface Funcao<T> que possui o método executaEm:<br />
<br />
<script src="https://gist.github.com/renanreismartins/9eb7981c411d0e2dc3bd.js"></script>
<br />
<div>
Agora podemos usar nosso Array. Vamos supor que temos um Array de String, com nomes de pessoas e queremos apenas imprimir o nome das pessoas em maiúsculo.</div>
<div>
<br /></div>
<div>
<script src="https://gist.github.com/renanreismartins/9ef42aea22ea82fdab3b.js"></script>
</div>
<div>
Ficou bacana. Mas repare que precisamos de uma interface classe Funcao<T> que possui apenas um método. Depois precisamos de uma implementar essa interface (no nosso caso por uma classe anônima), tudo para executar o processamento do método, podemos resumir tudo isso. Em Scala temos o recurso de funções anônimas ou "function literal" que tornam as coisas bem interessantes, o mesmo código acima pode ser escrito como:</div>
<div>
<br /></div>
<div>
<script src="https://gist.github.com/renanreismartins/c59bb2c8af8e388df02d.js"></script>
nomes.foreach(nome => println(nome)) // existem outras formas de escrever essa linha, abordaremos futuramente</div>
<div>
Imagine quantas APIs poderiam se beneficiar dessa abordagem. Lembre-se da API do AWT/Swing. Era muito improdutivo desenvolver listeners para nossos elementos de tela (botões por exemplo). Ao invés de escrever uma classe anônima, implementar um método e etc, se reproduzirmos a API em uma linguagem funcional, podemos apenas passar uma função anônima como citado anteriormente.</div>
<br />
<script src="https://gist.github.com/renanreismartins/674eafdbef0287e6070e.js"></script>
<br />
Não se preocupe com relação ao código acima, voltaremos à essas características futuramente.</div>
Anonymoushttp://www.blogger.com/profile/04313516968970529920noreply@blogger.com2tag:blogger.com,1999:blog-2576960088285057264.post-82427097458005319922012-12-18T18:09:00.000-02:002012-12-18T18:15:46.939-02:00Controle transacional: Spring + VraptorControle 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.<br />
<div>
<br /></div>
<div>
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.<br />
<br />
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 <a href="http://docs.oracle.com/javaee/6/tutorial/doc/bnagb.html" target="_blank">filter</a> para implementar essa funcionalidade.</div>
<div>
<br /></div>
<div>
Com o <a href="http://vraptor.caelum.com.br/pt/" target="_blank">Vraptor</a> temos essa funcionalidade pronta, veja a <a href="http://vraptor.caelum.com.br/pt/docs/componentes-utilitarios-opcionais/" target="_blank">documentação</a> e o <a href="https://github.com/caelum/vraptor/blob/master/vraptor-core/src/main/java/br/com/caelum/vraptor/util/hibernate/HibernateTransactionInterceptor.java" target="_blank">código</a>. Se seguirmos a <a href="http://www.caelum.com.br/apostila-vraptor-hibernate/" target="_blank">apostila oficial</a> veremos que neste caso o Vraptor gerencia a SessionFactory, a Session e também nossos DAOs.<br />
<br />
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: <a href="http://www.guj.com.br/java/224207-vraptor3--hibernate--transactional-na-controller/4">http://www.guj.com.br/java/224207-vraptor3--hibernate--transactional-na-controller/4</a><br />
<br />
Vamos ao código:<br />
<br />
<pre class="brush: xml"><beans xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:mongo="http://www.springframework.org/schema/data/mongo" xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemalocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/data/mongo
http://www.springframework.org/schema/data/mongo/spring-mongo-1.1.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost/db"></property>
<property name="username" value="root"></property>
<property name="password" value="xxx"></property>
</bean>
<bean class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" destroy-method="destroy" id="sessionFactory">
<property name="dataSource" ref="dataSource"></property>
<property name="packagesToScan" value="br.com.projeto"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.id.new_generator_mappings">true</prop>
</props>
</property>
</bean>
<bean class="org.springframework.orm.hibernate4.HibernateTransactionManager" id="transactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
</beans>
</pre>
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.
<br />
<br />
Criamos um DAO genérico:<br />
<pre class="brush: java">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...
}
</pre>
Uma implementação do nosso DAO
<br />
<pre class="brush: java">@Repository
public class UserDAOHibernate extends GenericDAOHibernate<user> {
@Autowired
public UserDAOHibernate(SessionFactory sessionFactory) {
super(sessionFactory);
}
@Override
public User getUserByLogin(String login) {
//...
}
// outros métodos...
}
</user></pre>
<br />
E por fim o nosso interceptador de transações:<br />
<br />
<br /></div>
<pre class="brush: java">@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;
}
}
</pre>
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.<br />
<br />
Você pode baixar esta classe na forma de plugin no <a href="https://github.com/caelum/vraptor-contrib" target="_blank">Github</a> de contribuições do Vraptor ou no meu <a href="https://github.com/renanreismartins/" target="_blank">particular</a>.<br />
<br />
Caso tenha alguma dúvida é só entrar em contato.Anonymoushttp://www.blogger.com/profile/04313516968970529920noreply@blogger.com0São Paulo, República Federativa do Brasil-23.5489433 -46.6388182-24.4795453 -47.929711700000006 -22.6183413 -45.3479247tag:blogger.com,1999:blog-2576960088285057264.post-18933536585546302532012-10-15T08:48:00.002-03:002012-10-15T10:03:39.365-03:00Melhorando o cenário de testes com padrões de projeto Builder e Fluent Interface<div>
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.</div>
<div>
<br /></div>
<div>
Imagine que estamos desenvolvendo um sistema para uma loja de venda de computadores. Este sistema deve sugerir computadores que possam agradar determinado cliente.<br />
<br />
Um possível modelo para este domínio pode ser visto no diagrama (diagrama informal, ok?!) abaixo:</div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwZGT-2xCGrNtgj_QXiWCq3S_e406jcvocSVrWDz2TFeET8riF2fZkW7KHIhpdVSxjjYpd7l-cKuPwWZsyaLZk3EIn39NQFm-wXHIt2sqNkpl9TrwxUBuaxvaVhkb8DlZC0dsgm9X_1g8/s1600/Cap04.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="160" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwZGT-2xCGrNtgj_QXiWCq3S_e406jcvocSVrWDz2TFeET8riF2fZkW7KHIhpdVSxjjYpd7l-cKuPwWZsyaLZk3EIn39NQFm-wXHIt2sqNkpl9TrwxUBuaxvaVhkb8DlZC0dsgm9X_1g8/s320/Cap04.png" width="320" /></a></div>
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.<br />
<br />
Cada componente possui nome, descrição e cor.<br />
<br />
Cor por sua vez possuí um nome e valores correspondente a tabela de cores RGB (red, green, blue).<br />
<br />
Vamos ao código do domínio:<br />
<br />
<br />
<pre class="brush: java">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
}
</pre>
</div>
<div>
<br />
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.<br />
<br />
<pre class="brush: java">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
}
}
</pre>
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 <a href="http://renanreismartins.blogspot.com.br/2012/08/colorindo-seu-codigo-para-garantir.html" target="_blank">post anterior</a> para aprender como visualizar a cobertura de testes em seu código).<br />
<br />
<pre class="brush: java">@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));
}
</pre>
</div>
<div>
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.</div>
<div>
<br />
Note que instanciar tantos objetos, com tantas relações se torna propenso a erros.<br />
<br /></div>
<div>
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.</div>
<div>
<br /></div>
<div>
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.<br />
<br />
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.</div>
<div>
<br /></div>
<div>
É impossível apenas ler o código que cria o cenário de teste e entender todas as informações.</div>
<div>
<br /></div>
<div>
Porém podemos reverter essa situação com a aplicação dos padrões de projeto <a href="http://en.wikipedia.org/wiki/Builder_pattern" target="_blank">Builder</a> e <a href="http://www.martinfowler.com/bliki/FluentInterface.html" target="_blank">Fluent Interface</a>.</div>
<div>
<br /></div>
<div>
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.</div>
<div>
<br /></div>
<div>
Com Fluent Interface é possível dar mais fluidez à sintaxe e em alguns casos economizar boas linhas de código.</div>
<div>
<br /></div>
<div>
Vamos aos exemplos práticos. Começamos criando a classe ComputadorBuilder:</div>
<div>
<br />
<pre class="brush: java">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);
}
}
</pre>
</div>
<div>
<br />
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.<br />
<br />
Vamos ao builder da classe Componente:<br />
<br />
<pre class="brush: java">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);
}
}
</pre>
<br />
E por fim o builder da classe Cor:<br />
<br />
<pre class="brush: java">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);
}
}
</pre>
<br />
Agora vamos refatorar nosso teste, note que podemos encadear a chamada de nossos builders, criando assim uma fluidez ainda maior.<br />
<br />
<pre class="brush: java">@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));
}
</pre>
<br />
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.<br />
<br />
Bônus:<br />
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.<br />
<br />
Algo como:<br />
<pre class="brush: java">public static Cor corPreta() {
return new Cor("preto", 0, 0, 0);
}
</pre>
<br /></div>
Anonymoushttp://www.blogger.com/profile/04313516968970529920noreply@blogger.com2tag:blogger.com,1999:blog-2576960088285057264.post-23109771713270551932012-08-12T23:05:00.003-03:002012-08-13T07:35:16.562-03:00Colorindo seu código para garantir qualidade instantânea com EclEmmaO 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.<br />
<div>
<br /></div>
<div>
Podemos também utilizar ferramentas de métricas e cobertura de código para garantir a qualidade de nosso projeto. Como por exemplo o <a href="http://cobertura.sourceforge.net/" target="_blank">Cobertura</a>, uma ferramenta que mede o percentual de linhas cobertas por testes em nosso código.</div>
<div>
<br /></div>
<div>
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.</div>
<div>
<br /></div>
<div>
Felizmente existem plugins que conseguem fazer este trabalho. Dentre eles o <a href="http://ecobertura.johoop.de/" target="_blank">eCobertura</a> e o <a href="http://www.eclemma.org/" target="_blank">EclEmma</a>.</div>
<div>
<br /></div>
<div>
Vou demonstrar o uso do EclEmma através de um exemplo trivial.</div>
<div>
<br /></div>
<div>
O primeiro passo é instalar o plugin no Eclipse, para isso vá ao Marketplace do Eclipse (Help > Marketplace...), busque por <b>eclemma </b>e clique em install. A partir daí é só realizar os passos de uma instalação de plugin normalmente.</div>
<div>
<br /></div>
<div>
Agora vamos escrever um simples código para entender o funcionamento.</div>
<div>
<br /></div>
<div>
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.</div>
<div>
<br /></div>
<div>
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.</div>
<div>
<div>
<br /></div>
<pre class="brush: java">public class Calculadora {
public double calcula(double valor, boolean aplicaTaxas) {
double valorCalculado = valor;
if(valor > 100 || aplicaTaxas) {
valorCalculado += 10;
}
return valorCalculado;
}
}
</pre>
<div>
<br /></div>
<div>
Vamos escrever nosso primeiro teste:</div>
<div>
<br /></div>
<pre class="brush: java"> @Test
public void naoDeveCalcularPoisValorEMenorQue100ENaoAplicaTaxas() {
Calculadora calc = new Calculadora();
double valorCalculado = calc.calcula(80, false);
assertTrue(valorCalculado == 80);
}
</pre>
<div>
<br /></div>
<div>
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.</div>
<div>
<br /></div>
<div>
Navegue até a classe calculadora e veja como nosso código ficou colorido:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_4mI-hAe_RL393ewPr9iKVbw2EY42n24edkJCKi4e-YWSjltAMwUid5Jm1tGFZ18OgYm3WSAVP5-1oAcxER5NxM9gcC6kUfPjBNmN2K1NzRjIW4bwrk_IFX4AlgFNObcnueCbX2n7zfw/s1600/tela1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="143" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_4mI-hAe_RL393ewPr9iKVbw2EY42n24edkJCKi4e-YWSjltAMwUid5Jm1tGFZ18OgYm3WSAVP5-1oAcxER5NxM9gcC6kUfPjBNmN2K1NzRjIW4bwrk_IFX4AlgFNObcnueCbX2n7zfw/s320/tela1.jpg" width="320" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
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.</div>
<div>
<br /></div>
<div>
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).</div>
<div>
<br /></div>
<div>
Vamos criar mais um teste para entrarmos na condicional. Agora passando o valor como 110 e aplicaTaxas como false:</div>
<div>
<br /></div>
<pre class="brush: java"> @Test
public void deveCalcularPoisValorEMaiorQue100() {
Calculadora calc = new Calculadora();
double valorCalculado = calc.calcula(110, false);
assertTrue(valorCalculado == 120);
}
</pre>
<div>
<br /></div>
<div>
Vamos ao resultado:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlO_wEnCYzcIEVwmZoTaalBA713ScnbzARqHbdd79h4Oet_4FuKwcpyrsKmKzpzDF5gtP7u0qtq07Qz_ndohGBXw5oRXpy8vK_htw_aXfBKbOH3iQN8Yh6ox5BXlJwPSEPV0sie1pQdzM/s1600/tela2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="149" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlO_wEnCYzcIEVwmZoTaalBA713ScnbzARqHbdd79h4Oet_4FuKwcpyrsKmKzpzDF5gtP7u0qtq07Qz_ndohGBXw5oRXpy8vK_htw_aXfBKbOH3iQN8Yh6ox5BXlJwPSEPV0sie1pQdzM/s320/tela2.jpg" width="320" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
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).</div>
<div>
<br /></div>
<div>
Vamos à um ultimo teste que simula o cenário ainda não coberto: Passar o parâmetro aplicaTaxas como true.</div>
<div>
<br /></div>
<pre class="brush: java"> @Test
public void deveCalcularPoisAplicaTaxas() {
Calculadora calc = new Calculadora();
double valorCalculado = calc.calcula(20, true);
assertTrue(valorCalculado == 30);
}
</pre>
<div>
<br /></div>
<div>
<br /></div>
<div>
Pronto, nossa lógica foi completamente testada.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnHhV_uZiv82AnbtYDCJLa7jEwMCxtgsuTHpgI5yJ7nTtqdFqi5xyBEj7WgVMuvw3AnvCdGwJQJox_mNDFqlDFd9Vhkee_XChefj6QdxqQT-HzKiYbmcF4gIL5E62JSaSYFEIc3hSuwKw/s1600/tela3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="111" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnHhV_uZiv82AnbtYDCJLa7jEwMCxtgsuTHpgI5yJ7nTtqdFqi5xyBEj7WgVMuvw3AnvCdGwJQJox_mNDFqlDFd9Vhkee_XChefj6QdxqQT-HzKiYbmcF4gIL5E62JSaSYFEIc3hSuwKw/s320/tela3.jpg" width="320" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
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.</div>
</div>
Anonymoushttp://www.blogger.com/profile/04313516968970529920noreply@blogger.com0tag:blogger.com,1999:blog-2576960088285057264.post-73640738379082285082012-02-27T18:54:00.000-03:002012-02-27T18:54:32.903-03:00Como configurar um projeto web com Maven + Eclipse<div>
<span style="font-family: inherit;">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.</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;">Uso o Maven apenas para gerenciar as dependências, portanto a configuração realizada foi a mais simples possível para rodar o projeto.</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;">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.</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;">O próximo passo é criar um Maven Project. Vá em File, New, Other e então procure por Maven Project.</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;">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.</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh33OBRgDV1uuz7v6gn7pzyP4zKwJ85tgZ8oa3pfxM5Bvrqiy1nM5NKiaBApKZaiwgE5eXkUaqtlRTgX5gZUGHPl8dzY-Tv8MjdS0BB4jqxaWqYlGM3hq1fDWlMGRgXME9YVKXyA99GwqQ/s1600/2b.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="236" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh33OBRgDV1uuz7v6gn7pzyP4zKwJ85tgZ8oa3pfxM5Bvrqiy1nM5NKiaBApKZaiwgE5eXkUaqtlRTgX5gZUGHPl8dzY-Tv8MjdS0BB4jqxaWqYlGM3hq1fDWlMGRgXME9YVKXyA99GwqQ/s320/2b.png" width="320" /></a></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;">Com o projeto criado, c<span style="background-color: white;">lique com o direito no projeto e escolha</span><span style="background-color: white;"> </span><span style="background-color: white;">Properties</span><span style="background-color: white;"> </span><span style="background-color: white;">>></span><span style="background-color: white;"> </span><span style="background-color: white;">Project Facets</span><span style="background-color: white;"> </span><span style="background-color: white;">>></span><span style="background-color: white;"> </span><span style="background-color: white;">Convert to faceted from</span><span style="background-color: white;">...</span></span></div>
<div>
<span style="background-color: white;"><span style="font-family: inherit;"><br /></span></span></div>
<div style="background-color: white;">
<span style="font-family: inherit;">Marque a opção Dynamic Web Module.</span></div>
<div style="background-color: white;">
<span style="font-family: inherit;"><br /></span></div>
<div style="background-color: white;">
<span style="font-family: inherit;">Clique em Further Configuration avaliable e altere o Content Directory para: /src/main/webapp. Pressione OK.</span></div>
<div style="background-color: white;">
<span style="font-family: inherit;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3dsgQ9enYeApWzcCq2G-FaaRFIWFIzXN8ab8BKbe57Dd6YKENPY7SmWluA47Z69dSK7JxJooKDWE_KREx_dB60T2SdcBwpjwH84ZXgs0PCy5vTY0wYWlzRWb0ykF2U4wuwSQsyNWi7u4/s1600/4b.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="233" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3dsgQ9enYeApWzcCq2G-FaaRFIWFIzXN8ab8BKbe57Dd6YKENPY7SmWluA47Z69dSK7JxJooKDWE_KREx_dB60T2SdcBwpjwH84ZXgs0PCy5vTY0wYWlzRWb0ykF2U4wuwSQsyNWi7u4/s320/4b.png" width="320" /></a></div>
<div style="background-color: white;">
<span style="font-family: inherit;"><br /></span></div>
<div style="background-color: white;">
<span style="font-family: inherit;"><br /></span></div>
<div style="background-color: white;">
<span style="font-family: inherit;">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.</span></div>
<div style="background-color: white;">
<span style="font-family: inherit;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOI7Gs8OTKBrU4-N_4WkuVI0FFk1gHiHvFz8qKAJHHGL4YD577vxEQNQHk8DwCrq-DwqLx7rPHFsOQFly7jTwjlDYUdKEvEZtNBNuy0lWpQItnK2zJeLYmc5Iqvx19-Z1z1K35odYyYBk/s1600/3b.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="289" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOI7Gs8OTKBrU4-N_4WkuVI0FFk1gHiHvFz8qKAJHHGL4YD577vxEQNQHk8DwCrq-DwqLx7rPHFsOQFly7jTwjlDYUdKEvEZtNBNuy0lWpQItnK2zJeLYmc5Iqvx19-Z1z1K35odYyYBk/s320/3b.png" width="320" /></a></div>
<div style="background-color: white;">
<span style="font-family: inherit;"><br /></span></div>
<div style="background-color: white;">
<span style="font-family: inherit;"><br /></span></div>
<div style="background-color: white;">
<span style="font-family: inherit;">Pronto! Agora é só adicionar suas dependências no pom.xml.</span></div>
<div style="background-color: white;">
<span style="font-family: inherit;"><br /></span></div>
<div style="background-color: white;">
<span style="font-family: inherit;">Abraços</span></div>Anonymoushttp://www.blogger.com/profile/04313516968970529920noreply@blogger.com11São Paulo, Brasil-23.5489433 -46.6388182-24.014749300000002 -47.270532200000005 -23.0831373 -46.0071042tag:blogger.com,1999:blog-2576960088285057264.post-70170688230039564912012-02-06T08:57:00.000-02:002012-08-13T07:37:08.566-03:00Query polimorfica com interfaces - HibernateFazer 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.<br />
<br />
Obs: Este <a href="http://guj.com.br/java/115175-heran-elegante-" target="_blank">tópico</a> possui uma ótima discussão à respeito de herança e como ela pode ser prejudicial ao seu código.<br />
<br />
Vamos supor que tenhamos o conceito de notificável em nosso sistema e queremos buscar por todas as entidades "notificáveis".<br />
<br />
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.<br />
<br />
<br />
<pre class="brush: java">public interface Notificavel {
public void notifica();
}
</pre>
<br />
<br />
Suponhamos que temos duas entidades em que serão notificáveis: Sistema e Pessoa.<br />
<br />
<br />
<pre class="brush: java">@Entity
public class Sistema implements Notificavel { ...
</pre>
<br />
<br />
<pre class="brush: java">@Entity
public class Pessoa implements Notificavel { ...
</pre>
<br />
<br />
<div>
<br /></div>
<div>
Então realizamos a busca com a seguinte HQL:</div>
<div>
<br /></div>
<div>
<pre class="brush: java">String hql = "FROM br.com.renan.domain.Notificavel";
</pre>
<br />
Note que colocamos o nome totalmente qualificado da interface, isso é necessário para que o hibernate saiba exatamente por qual interface buscamos.</div>
<div>
<br /></div>
<div>
Note que assim você consegue buscar por todas as entidades que implementem a inteface.<br />
<br />
E por fim o teste:<br />
<br />
<br />
<pre class="brush: java">@Test
public void deveRetornarDoisVeiculos() {
List<notificavel> notificaveis = notificador.lista();
assertEquals(2, notificaveis.size());
}
</notificavel></pre>
<div>
<br /></div>
<div>
<br /></div>
<div>
<a href="https://github.com/renanreismartins/QueryPolimorfica" target="_blank">Aqui</a> é possível encontrar o código completo do projeto.</div>
<div>
<br /></div>
<div>
Abraços.</div>
</div>
Anonymoushttp://www.blogger.com/profile/04313516968970529920noreply@blogger.com2São Paulo, Brasil-23.5489433 -46.6388182-24.014749300000002 -47.270532200000005 -23.0831373 -46.0071042tag:blogger.com,1999:blog-2576960088285057264.post-64685556738283106522011-11-18T00:40:00.001-02:002011-11-27T00:47:57.019-02:00REST - Negociação de Conteúdo HTTP / Content NegotiationUltimamente tenho trabalhado em um projeto com arquitetura REST e um dos requisitos, é que consigamos integrar e atender de maneira flexível o maior número possível de clients, portanto fornecemos os recursos com diferentes tipos de formatos (<a href="http://en.wikipedia.org/wiki/Internet_media_type" target="_blank">media types</a>).<br />
<div>
<br /></div>
<div>
Basicamente o client solicita o recurso e informa em qual formato deseja receber a representação, ou seja, ele negocia o conteúdo com o servidor. Para isso o client fará uma requisição GET e colocará no request header o atributo Accept com o valor desejado: application/xml, application/json e etc...</div>
<div>
<div>
<br /></div>
<div>
Nosso recurso irá fornecer a representação de um funcionário e além dos formatos como xml e json, neste post também faremos uma implementação que representa o funcionário através de uma imagem.</div>
<div>
<br /></div>
</div>
<div>
Caso o cliente consiga trabalhar com mais de um media type, ele pode informar a ordem de prioridade, colocando o media type preferido primeiro, precedido dos menos importantes, separados por vírgula</div>
<div>
<br /></div>
<div>
Ex: Accept: application/xml, application/json</div>
<div>
<br /></div>
<div>
Cabe esclarecer que caso o client solicite o recurso em um media type que o servidor não fornece, deverá ser retornada uma resposta com o código <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html" target="_blank">406 Not Acceptable</a>.</div>
<div>
<br /></div>
<div>
Para a implementação proposta, utilizaremos <a href="http://en.wikipedia.org/wiki/Java_API_for_RESTful_Web_Services" target="_blank">JAX-RS</a> através de sua implementação padrão <a href="http://jersey.java.net/" target="_blank">Jersey</a>.<br />
<br /></div>
<pre class="brush: java">@Path("/funcionarios")
public class FuncionarioResource {
@GET
@Path("{id}")
@Produces({ "application/xml", "application/json" })
public Funcionario getFuncionario(@PathParam("id") Integer id) {
Funcionario funcionario = repository.get(id);
return funcionario;
}
}
</pre>
<div>
<div>
<div>
<div>
Serei breve nas explicações das anotações básicas tendo em vista que existem excelentes materiais na web e focarei no necessário para a negociação de conteúdo.<br />
<br />
A anotação <a href="http://jersey.java.net/nonav/documentation/latest/user-guide.html#d4e98" target="_blank">@Path</a>("/funcionarios") informa a url da nossa <a href="http://jersey.java.net/nonav/documentation/latest/user-guide.html#d4e82" target="_blank">RootResource</a>.<br />
<br />
Em seguida anotamos nosso método getFuncionario com a anotação @GET que informa que este método aceita apenas requisições feitas pelo método GET do http, isso quer dizer que nosso método é <a href="http://en.wikipedia.org/wiki/Idempotence" target="_blank">idempotente</a>, não importa quantas vezes a requisição seja feita, ela não alterará o estado do recurso.<br />
<br />
Também anotamos o método com @Path("{id}"), informando que devemos passar o id do funcionário na URI. Para que consigamos acessar o recurso devemos usar o caminho funcionarios/1 por exemplo.<br />
<br />
Como parâmetro o método espera o id do funcionário. Anotamos esse parâmetro com @PathParam("id") para que seja injetado na nossa variável id o valor passado pela URI conforme indicado na anotação @Path("{id}").<br />
<br />
Para o assunto tratado a mais importante é a anotação @Produces({"application/xml", "application/json"}), ela informa que este método retorna o nosso recurso tanto em XML quanto JSON dependendo apenas da solicitação do cliente. A implementação JERSEY se responsabiliza em parsear o recurso para estes formatos então precisamos apenas retornar nosso recurso: Funcionario funcionario = repository.get(id);<br />
<br />
Agora vamos expor nosso recurso como uma imagem. Para isso, precisamos fazer nossa própria implementação, que é transformar nosso recurso em uma imagem. Neste caso vamos usar o atributo caminhoFoto para buscar a foto e retorná-la como um array de bytes.<br />
<br />
<br />
<pre class="brush: java"> @GET
@Path("{id}")
@Produces({ "image/jpeg", "image/jpg" })
public byte[] getPhoto(@PathParam("id") Integer id) {
Funcionario funcionario = repository.get(1);
try {
InputStream is = this.getClass().getResourceAsStream(funcionario.getCaminhoFoto());
BufferedImage img = ImageIO.read(is);
ByteArrayOutputStream bao = new ByteArrayOutputStream();
ImageIO.write(img, "jpg", bao);
return bao.toByteArray();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
</pre>
<br />
Note que são usadas as mesmas anotações no método getFuncionario e no getFoto, inclusive o @Path é o mesmo. A única diferença é que o método getFoto retorna media types do tipo "image/jpeg" ou "image/jpg".<br />
<br />
Como o valor da anotação @Path é o mesmo, oque determina qual método atenderá a requisição é justamente o tipo de media type aceito pelo client.<br />
<br />
Caso ele envie uma requisição com Accept: application/xml ou application/json o método getFuncionario será invocado, ou então, caso a requisição possua Accept: image/jpeg ou image/jpg, o método getFoto será invocado.<br />
<br />
No meu <a href="https://github.com/renanreismartins/Rest-Content-Negotiation" target="_blank">github</a> tem a implementação completa do projeto que pode ser publicado em qualquer servlet container, desenvolvido com maven.<br />
<br />
Espero que o post possa ser útil.<br />
<br />
Abrasssss<br />
<br />
<br /></div>
</div>
</div>
</div>Anonymoushttp://www.blogger.com/profile/04313516968970529920noreply@blogger.com0tag:blogger.com,1999:blog-2576960088285057264.post-45916388328760385712011-09-28T18:56:00.000-03:002011-11-21T09:40:21.579-02:00Como testar os Controllers do Vraptor com Mockito<br />
Um dos frameworks que mais gosto de trabalhar, devido a sua simplicidade e produtividade é o Vraptor. Uma das suas vantagens é que ele abstrai a complexidade da API de Servlets, NÃO te obriga a trabalhar com getters/setters evitando que seu modelo se torne anêmico. Não é intrusivo, você foca na sua lógica de negócios e não em aprender sobre a arquitetura e classes do framework, ou seja, a curva de aprendizado é minima.<br />
<br />
Trabalha de forma muito fácil com injeção de dependência. Não é necessário configurar quase nada. Tem suporte a REST e inumeros outros recursos. Mas oque chama realmente a atenção é que você consegue começar a trabalhar com ele em questão de minutos. Poderiamos ficar o dia todo discutindo sobre as vantagens de utilizar este framework. Portanto vamos ao objetivo do post: Aprender a testar unitáriamente as classes de controller do Vraptor.<br />
<br />
Para isso utilizaremos o JUnit e o Mockito.<br />
<br />
Desejamos testar o método salva(Aluno aluno) do controller abaixo. Este método recebe um aluno, verifica se é valido, salva e redireciona para a listagem, caso o aluno seja inconsistente ele redireciona para a página de cadastro/edição para exibir os erros.<br />
<br />
<pre class="brush: java">
@Resource
public class AlunoController {
private AlunoRepository alunoRepository;
private Result result;
private Validator validator;
public AlunoController(AlunoRepository alunoRepository, Result result, Validator validator) {
this.alunoRepository = alunoRepository;
this.result = result;
this.validator = validator;
}
public void add(Aluno aluno) {
this.validator.validate(aluno);
this.validator.onErrorForwardTo(this).cadastra();
this.alunoRepository.add(aluno);
this.result.redirectTo(this).lista();
}
}
</pre>
Temos como dependência a interface AlunoRepository e como o objetivo é testar o controller, devemos mockar esta dependência.<br />
<br />
Criamos uma classe de teste comum do JUnit.<br />
<br />
<pre class="brush: java">
public class AlunoControllerTest {
private AlunoController controller;
private AlunoRepository alunoRepository;
private MockResult result;
private JSR303MockValidator validator;
@Before
public void setUp() throws Exception {
this.alunoRepository = mock(AlunoRepository.class);
result = spy(new MockResult());
validator = spy(new JSR303MockValidator());
controller = new AlunoController(alunoRepository, turmaRepository, result, validator);
}
}
</pre>
<br />
Note que os objetos result e validator usam mocks apropriados, portanto não precisamos nos preocupar com eles. É melhor utilizar estes mocks fornecidos, pois estes objetos usam Fluent Interface oque torna sua testabilidade muito difícil.<br />
<br />
Repare também que usamos o método spy(T object) para obter as instancias do result e validator, isso é util pois conseguimos chamar os métodos reais dos objetos, então podemos verificar se realmente houveram interações com os objetos.<br />
<br />
O teste:<br />
<br />
<pre class="brush: java">
@Test
public void add() {
Aluno aluno = getAlunoConsistente();
controller.add(aluno);
verify(alunoRepository).add(aluno);
}
</pre>
Através deste teste tentamos salvar um aluno, que é um objeto consistente (válido). Então o aluno deve ser adicionado ao repositório, portanto nos asseguramos que o método add(Aluno aluno) do repositório foi chamado, isso é feito através da linha: verify(alunoRepository).add(aluno);<br />
<br />
Para testarmos nossas validações, desenvolvemos um teste que espera que uma ValidationException seja lançada e nos asseguramos que não houveram interações com o repositório:<br />
<pre class="brush: java">
@Test(expected = ValidationException.class)
public void gravaAlunoInconsistenteTest() {
controller.grava(getAlunoInconsistente());
verifyNoMoreInteractions(alunoRepository);
}
</pre>
Esse post teve origem em uma thread do GUJ que abri e recebi orientações do Lucas Cavalcanti: <a href="http://www.guj.com.br/java/243436-vraptor-e-mockito---testes-de-controllers">http://www.guj.com.br/java/243436-vraptor-e-mockito---testes-de-controllers</a><br />
<br />
<br />
UPDATE:<br />
Muitas vezes desejamos verificar se o nosso método fez um redirecionamento para uma view ou lógica específica. Então como o Lucas citou, podemos fazer:<br />
<br />
<br />
<pre class="brush: java">
AlunoController spy = Mockito.spy(alunoController);
when(result.redirectTo(alunoController)).thenReturn(spy);
this.alunoController.grava(aluno);
verify(spy).lista();
</pre>
<br />
Assim estamos nos assegurando que o método lista() foi chamado, ou seja, foi feito o redirecionamento.<br />
<br />
Abraços<br />Anonymoushttp://www.blogger.com/profile/04313516968970529920noreply@blogger.com0tag:blogger.com,1999:blog-2576960088285057264.post-41581661520572009992011-08-24T02:22:00.000-03:002011-08-24T02:28:23.556-03:00Automatizando testes de aceitação com SeleniumTestar a interface (camada de visualização) de uma aplicação web é uma tarefa trabalhosa, repetitiva e que requer atenção. Na maioria dos projetos a única técnica utilizada é o teste manual: o desenvolvedor abre o navegador, preenche todos os campos manualmente, envia o formulário e então certifica-se que o resultado renderizado é o resultado esperado.<br />
<br />
Estes testes devem ser utilizados em todas as interfaces do sistema, porém muitas equipes os ignoram. Em interfaces com poucos campos a serem preenchidos tais testes passam a impressão de que são desnecessários, pois, pode-se testá-las mais rapidamente de forma manual do que escrevendo o teste automatizado.<br />
<br />
Entretanto quando o sistema começa crescer e a complexidade das telas aumenta, os testes automatizados pagam seu custo inicial, além de garantir a qualidade do sistema.<br />
<br />
O Selenium WebDriver é uma ótima ferramenta para execução de testes de aceitação e será abordado para o desenvolvimento destes testes, neste em outros posts.<br />
<br />
Primeiro passo:<br />
<br />
Adicione o Selenium em seu classpath. Com o maven basta adicioná-lo como dependência:<br />
<br />
<pre><dependency><dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-firefox-driver</artifactId>
<version>2.4.0</version>
</dependency>
</dependency>
</pre>O próximo passo é instanciar um WebDriver:<br />
<br />
WebDriver driver = new FirefoxDriver();<br />
<br />
WebDriver é uma interface que simula o browser em seu teste. Neste caso instanciamos o FirefoxDriver que permite que o teste seja visualizado.<br />
<br />
Existem outras implementações da interface WebDriver, como o <a href="http://seleniumhq.org/docs/03_webdriver.html#htmlunit-driver">HtmlUnit Driver</a>, que permite que o teste seja executado mais rapidamente, porém não é possível visualizar o teste em tela.<br />
<br />
<a href="http://seleniumhq.org/docs/03_webdriver.html#driver-specifics-and-tradeoffs">Aqui</a> podem ser encontradas as vantagens e desvantagens entre as implementações.<br />
<br />
Depois é necessário acessar a url:<br />
driver.get("http://www.meudominio.com.br/aluno/cadastro");<br />
<br />
O método get requisita a página e espera que seja totalmente carregada para o<br />
início dos testes.<br />
<br />
Com a interface WebElement é possível manipular os valores dos campos, para isso, é necessária uma referência do campo.<br />
<br />
Supondo que os campos do cadastro sejam:<br />
<input type="text" name="aluno.nome" /><br />
<input type="text" name="aluno.email" /><br />
<br />
A referência pode ser obtida através de uma pesquisa do nome do campo:<br />
WebElement nome = driver.findElement(By.name("aluno.nome"));<br />
WebElement email = driver.findElement(By.name("aluno.email"));<br />
<br />
Agora com referências aos elementos, pode-se enviar algum valor para eles:<br />
nome.sendKeys("Renan");<br />
email.sendKeys("renan@renan.com");<br />
<br />
Então submetemos o formulário:<br />
email.submit();<br />
<br />
Note que chamamos o método submit da instância email. Apesar de email não ser um formulário, o Selenium submete o formulário a que o elemento pertence.<br />
<br />
Agora que submetemos o formulário podemos averiguar se o sistema se comportou da forma que esperávamos.<br />
<br />
Supomos que o comportamento esperado é exibir a mensagem: "Aluno Renan Cadastrado com sucesso.", dentro de um elemento com o atributo id preenchido como "result".<br />
<br />
<div id="result">Aluno Renan Cadastrado com sucesso.</div><br />
<br />
Podemos fazer as asserções para verificar o resultado. Segue um exemplo utilizando JUnit:<br />
Assert.assertEquals("Aluno Renan Cadastrado com sucesso.", result.getText());<br />
<br />
Grande abraço.<br />
<br />
Anonymoushttp://www.blogger.com/profile/04313516968970529920noreply@blogger.com0