sexta-feira, 18 de fevereiro de 2011

1º JavaBahia nas Faculdades de 2011

Local: Faculdade AREA1
Sala: 202 Subsolo
Data: 26/02/2011 (sábado)
Horário: 9:00 às 12:00
Entrada: Gratuita
Programação:

1) Vraptor: um framework web opensource desenvolvido pela Caelum (http://www.caelum.com.br/).
Palestrante: Alabê Duarte (eu mesmo)


2)  WebIntegrator: O quê? Por quê? Como? Desmitificando o que é o WebIntegrator, as razões para escolhê-lo como ferramenta de desenvolvimento e como preparar o ambiente para usá-lo.
Palestrante: Lucano Borges (http://bahiaonrails.blogspot.com/)

3) Unconference( Uma palestra em que todos podem ser o palestrantes, um bate papo).
"A Era da interação": A importância de um profissional/estudante participar de uma comunidade





Como vou apresentar, aqui fala um pouco sobre o VRaptor logo abaixo. Após a apresentações o blog vai estar recheado de posts sobre o mesmo.

Resumo Apresentação VRaptor:

Já é fato que as linguagens mais modernas e os seus frameworks, como o Ruby on Rails, revolucionaram a maneira de desenvolver aplicações para web. Cada vez mais as arquiteturas estão mais voltadas para a regra de negócio e, por conseguinte, configurações de infra-estrutura já não é o tipo de preocupação que o desenvolvedor necessita ter, até pela maturidade dos frameworks, especificações e tudo mais. Em outras palavras, o conceito de "Convention over Configuration" (CoC) está sendo empregado no mundo do desenvolvimento caindo como uma luva para os desenvolvedores, onde agora o foco está cada vez mais próximo da regra de negócio, já que, por convenção, determinadas configurações em xml, por exemplo, já não são necessárias.

Falando em Java, muito se fala também pela sopa de letrinhas que estão relacionadas para desenvolvimento Java web. Cada framework web tem um mapeamento no web.xml, um ou varios arquivos de configuração xml para definir rotas, controladores, etc, e é necessário também conhecer determinadas taglibs para interação com os dados nas jsps.
Obviamente, existem muitos frameworks no mercado, cada um com as suas vantagens e desvantagens, e o VRaptor é mais um de tantos que existem. Entretanto, o VRaptor vem ganhando espaço por "implementar" o conceito do CoC, encapsular detalhes de comunicação HttpServletRequest, sendo baseado em POJO's e anotações, além de não interferir, ou melhor, interferir o mínimo necessário na camada de apresentação pois a única coisa que se utiliza é o famoso JSTL, dando liberdade para o desenvolvedor fazer o que quiser, seja usando jQuery, Extjs ou derivados. 

O VRaptor é um framework opensource desenvolvido pela Caelum (http://www.caelum.com.br/) e a documentação é vasta, em português (sim, o VRaptor é um framework brasileiro). O "core" do framework é todo em cima do spring, o que facilita a integração com o mundo de facilidades que o spring provê, e a filosofia que o VRaptor tenta passar para a comunidade é de ser um framework MVC puro, onde não há necessidade de aprender nada de extraordinário para que tenha proveito do seu potencial. 

Convido a todos para assistirem essa palestra introdutória ao framework, e não tenho intenção de evangelizá-la no sentido de recriminar as outras tecnologias (que também possuem, e muito, o seu valor), porém acho que o VRaptor merece a atenção de todos nós.

Mais informações podem encontrar no site oficial: http://vraptor.caelum.com.br/

abraços! Compareçam

segunda-feira, 27 de dezembro de 2010

Fluent Interface como apoio ao código legado

Falando em Java, a cultura de desenvolvimento é marcada por uma série de sufixos e prefixos que geralmente separam uma camada da outra, ou até uma determinada "responsabilidade" específica. Há um excelente post no blog de Philip Calçado que fala um pouco sobre a arquitetura "BOLOVO" e recomendo a leitura. O fato é que existem muitos patterns que são utilizados e muitas alternativas veem surgindo.
Antes de mais nada, não estou julgando o que é bom ou o que é ruim, cada caso é um caso, cada cenário será perfeito para o uso de qualquer design ou modelo. O que quero me referir neste texto é apenas mais uma das tantas abordagens de desenvolvimento.
Sem mais delongas, um modelo arquitetural que tem chamado minha atenção é a Fluent Interface. Quem quiser saber mais pode ler também esse excelente post de Guilherme Chapiewski. Fluent Interface nada mais é que uma interface com métodos sugestivos, mais próximos da linguagem natural dos humanos ou, se preferirem, uma DSL para os desenvolvedores.
Particularmente, trabalhei em alguns projetos que eu temia mover uma linha de código de lugar diante de tantos getters e setters, metodos de busca via query, com os chamados "obterPorFiltro" com mil linhas de ifs e elses.  Fora quando a regra de negócio determinava qual tipo de query seria montada em runtime, haja ifs. Em alguns projetos simples não tive o que me queixar, porém houve aqueles que hesitei muitas vezes em continuar ou até cogitei criar o meu próprio método para não quebrar alguma regra que esteja em funcionamento a anos.  Sim, estou falando, principalmente, dos sistemas legados.
Para os adeptos do TDD, uma das perguntas que o seu "design" deve responder é: "o meu código é testável?"
E para testar funcionalidades, nada melhor que programar para interfaces, como manda a orientação a objetos. Alguns questionamentos talvez tenham aberto a oportunidade de evidenciar as interfaces fluentes, que contribuem com a legibilidade e ao mesmo tempo facilita os testes unitários, documentações e tudo mais.

Para ilustrar, vou propor um problema. Digamos que na empresa em que trabalho todos os sistemas se comunicam via banco através de schemas e 80% dos sistemas estão utilizando query nativa nos códigos com jdbc, chamadas de procedures, etc. Agora vou exemplificar uma situação em que desejo desacoplar a minha query, que atualmente é do tipo "obterPorFiltro" cheio de ifs, getters e setters, e poder compor N combinações, de forma que, de acordo com a minha regra de negócio, posso fazer, ou não, uma junção, obter alguns campos, etc.


/**
 * SELECT
             MATRICULA || DIGITO,
             NOME
      FROM
             FUNCIONARIOS FUNC
 * @return
 * @throws Exception
 */
public interface Funcionarios extends FluentRepository<Funcionario> {
      
    /**
     * SELECT SITU.CODIGO, SITU.DESCRICAO
     *
     * FROM SITUACOES SITU
     *
     * AND SITU.CODIGO = FUNC.SITUACAO
     * AND SITU.CODIGO = 'A'
     *
     * @return
     */
    Funcionarios ativos();
    
    /**
     * AND FUNC.MATRICULA || FUNC.DIGITO = ?
     *
     * @param matricula
     * @return
     */
    Funcionarios com(String matricula);
  
    /**
     * SELECT EMPR.CODIGO, EMPR.DESCRICAO
     *
     * FROM EMPRESAS EMPR
     *
     * AND EMPR.CODIGO = FUNC.EMPR_CODIGO
     * AND EMPR.CODIGO = ?
     *
     * @param empresa.codigo
     * @return
     */
    Funcionarios da(Empresa empresa);



    T get() throws Exception;
   
    Collection<T> list() throws Exception;
}


public class Funcionario {

       private Long id;
       private String nome;
       private String matricula;
      
       // getters e setters
}


Pronto... temos as nossas interfaces fluentes e a nossa classe de domínio chamada Funcionario. Notem que evitei o uso de sufixos e prefixos (Funcionario - Domínio, Funcionarios - Repositório). A chamada pode ser similar a esta abaixo:


Funcionarios funcionarios = new FuncionarioDaoImpl();
Funcionario funcionarioPesquisado = funcionarios.ativos().com("1234").da(new Empresa(EmpresasDisponiveis.XPTO)).get();

Collection<Funcionario> funcionariosAtivos = funcionarios.ativos().list();


Esse exemplo pode servir também para quem estiver utilizando JPA ou Hibernate, mas abaixo preferi colocar um exemplo utilizando jdbc, ficando você livre de colocar o jdbcTemplate do Spring, Jdbc puro ou o framework de sua empresa/sua casa.



public class FluentJdbcSupport {

       private StringBuilder queryBuilder;
       private StringBuilder selectBuilder;
       private StringBuilder joinTablesBuilder;
       private StringBuilder clausesBuilder;
    private List<Object> params;
   
    public FluentJdbcSupport(String tableName, String firstField, String... otherFields) {
       this.initializeSelectBuilder(firstField, otherFields);
       this.initializeJoinTables(tableName);
       this.initializeClauses();
       this.initializeParams();
    }
   
    private void initializeSelectBuilder(String firstField, String... otherFields) {
       selectBuilder = new StringBuilder();
       selectBuilder.append(" SELECT ").append(firstField);
       for (String otherField : otherFields) {
                    selectBuilder.append(" , ").append(otherField);
             }
    }
   
    private void initializeJoinTables(String tableName) {
       joinTablesBuilder = new StringBuilder();
       joinTablesBuilder.append(" FROM ").append(tableName);
    }
   
    private void initializeClauses() {
       clausesBuilder = new StringBuilder();
       clausesBuilder.append(" WHERE 1 = 1 ");
    }
   
    private void initializeParams() {
       params = new ArrayList<Object>();
    }
   
    protected FluentJdbcSupport addSelectedField(String field) {
             selectBuilder.append(" , ").append(field);
             return this;
    }
   
    protected FluentJdbcSupport addJoinTable(String table) {
             joinTablesBuilder.append(" , ").append(table);
             return this;
    }
   
    protected FluentJdbcSupport addClause(String clause) {
       clausesBuilder.append(" AND ").append(clause);
       return this;
    }
   
    protected FluentJdbcSupport addParams(Object param) {
       params.add(param);
       return this;
    }
   
    protected void buildQuery() {
       queryBuilder = new StringBuilder().append(selectBuilder).append(joinTablesBuilder).append(clausesBuilder);
    }

       public StringBuilder getQuery() {
             return queryBuilder;
       }
}


Abaixo segue a classe filha da abstração, que seria a implementação do repositorio de funcionarios:


public class FuncionarioDao implements Funcionarios {
      
       private FluentJdbcSupport<Funcionario> fluentJdbcSupport;
      
       public FuncionarioDao() {
             this.fluentJdbcSupport = new FluentJdbcSupport<Funcionario>("FUNCIONARIOS", "ID", "NOME", "MATRICULA || DIGITO");
       }

       @Override
       public Funcionarios ativos() {
             this.fluentJdbcSupport.addSelectedField("SITU.CODIGO");
             this.fluentJdbcSupport.addSelectedField("SITU.DESCRICAO");
             this.fluentJdbcSupport.addJoinTable("SITUACOES SITU");
             this.fluentJdbcSupport.addClause("SITU.CODIGO = FUNC.SITUACAO");
             this.fluentJdbcSupport.addClause("SITU.CODIGO = 'A'");
             return this;
       }

       @Override
       public Funcionarios com(String matricula) {
             this.fluentJdbcSupport.addClause("FUNC.MATRICULA || FUNC.DIGITO = ?");
             this.fluentJdbcSupport.addParams(matricula);
             return this;
       }

       @Override
       public Funcionarios da(Empresa empresa) {
             this.fluentJdbcSupport.addSelectedField("EMPR.CODIGO");
             this.fluentJdbcSupport.addSelectedField("EMPR.DESCRICAO");
             this.fluentJdbcSupport.addJoinTable("EMPRESAS EMPR");
             this.fluentJdbcSupport.addClause("EMPR.CODIGO = FUNC.EMPR_CODIGO");
             this.fluentJdbcSupport.addClause("EMPR.CODIGO = ?");
             this.fluentJdbcSupport.addParams(empresa.getCodigo());
             return this;
       }

       @Override
       public Funcionario get() throws Exception {
             this.fluentJdbcSupport.buildQuery();
             System.out.println(this.fluentJdbcSupport.getQuery());
             return null;
       }

       @Override
       public Collection<Funcionario> list() throws Exception {
             this.fluentJdbcSupport.buildQuery();
             System.out.println(this.fluentJdbcSupport.getQuery());
             return null;
       }

}


Bom... é isso pessoal. Como podem ver é uma solução bem caseira, mas o foco desse artigo é que há possibilidade de refatorar o seu código, construir DSL's internas para ilustrar melhor o domínio da aplicação, criar Facades com chamadas pré-definidas (sempre que obter usuarios obter sempre os ativos), enfim, é só mais uma forma de codificar. 
Guilherme Chapiewski também postou um excelente artigo sobre um exemplo prático de fluent interface, recomendo que deem uma lida.

Se alguém quiser discutir, criticar, opinar, dúvidas, só comentar! Abraço