quarta-feira, 25 de agosto de 2010

Os limites do Agile

Quais são os limites para o desenvolvimento ágil de software? Essa é, provavelmente, uma pergunta que passa pela cabeça de muitas pessoas (inclusive na minha). Infelizmente, não há respostas fáceis para essa questão e, para piorar um pouco, há alguns mal entendidos clássicos a respeito do tema, que ofuscam a nossa mente, e que eu gostaria de ajudar a esclarecer.

Muitos profissionais do nosso meio (desenvolvedores, professores, conferencistas, etc) têm as seguintes ideias (a meu ver equivocadas) sobre Agile:

- É bacana, mas apenas para projetos de pequeno porte.
- Tem a desvantagem de produzir código de baixa reusabilidade.
- Agile e modelos de qualidade são excludentes entre si.

Creio que essas ideias surgem pois tais pessoas têm uma visão muito pequena sobre a realidade da cultura ágil atual. A maioria delas olha para os processos individualmente, como se Agile fosse SCRUM ou XP ou LEAN ou FDD ou WHATEVER. Ora, nenhum profissional sério acredita que qualquer um desses métodos irá, sozinho, resolver todos os problemas e situações que o moderno desenvolvimento de software exige. Realmente nenhum deles tem esse poder. Agile é algo bem mais abrangente do que isso...

Agile é um conjunto de práticas, processos, ferramentas, princípios e valores que formam um arcabouço útil para desenvolver projetos de qualquer porte. É pura Engenharia de Software. Duvida? O SEI, criador do CMMI, não. Publicou um relatório convocando a comunidade de qualidade de software a utilizar práticas ágeis para atender as áreas de processo do modelo CMMI. O título é: "CMMI or Agile: Why not embrace both?". Sugestivo, não?

As técnicas mais quentes da Engenharia de Software atual estão presentes nos métodos ágeis. TDD, DDD, integração contínua, automação do desenvolvimento e testes, cliente on-site, time-boxed iterations, desenvolvimento iterativo, etc. Todas essas técnicas nasceram no seio das comunidades ágeis e estão sendo consumidas por todos os tipos de projetos (os grandes inclusive rs).

Acredito que o que falta para o Agile conseguir mais respeito nas rodas "intelectuais" do mundo do software é um maior número de links entre a Engenharia de Software e as técnicas e práticas ágeis mais utilizadas. Algo que da minha parte pretendo contribuir com a minha futura dissertação de mestrado.

sexta-feira, 6 de agosto de 2010

DDD e EJB 3.0


DDD é uma técnica poderosa para se construir software focado no negócio da organização e apoiado na linguagem corrente dos que irão utilizar o sistema. Dessa forma, o aplicativo é construído de "dentro para fora", permitindo que regras de negócio sejam implementadas (e testadas) bem antes da construção das outras camadas e partes importantes do sistema como telas, controles e bancos de dados.

Em algum momento, teremos que implementar funcionalidades para outras camadas  e alguns serviços essenciais como controle de transações, object pool, injeção de dependência, persistência dos objetos de domínio, etc. Nesse post vou apresentar uma ideia geral de como poderíamos realizar essas tarefas de modo bem simples usando EJB 3.0.

Antes de tudo uma observação: se você (como eu) odeia as complexidades e complicações do EJB 2.0 e torceu o nariz no instante que leu o título desse post, saiba que a versão 3.0 é completamente diferente da anterior. Os session beans e entidades JPA são agora objetos leves e que permitem (entre outras coisas) que sejam testados fora do container que os gerencia. Se você gosta da ideia de trabalhar segundo as premissas de Eric Evans e curte criar POJOs para resolver seus problemas então EJB 3.0 é a ferramenta perfeita para suas necessidades.

Primeiramente, vamos criar uma interface genérica para nossos repositórios:

@Local
public interface Repositorio<T> {
   
    List<T> buscarTodos();

    T buscarPorID(int id);

    void add(T object); 

    void remove(T object);

    void update(T object);
}

Não fosse pela anotação @Local poderíamos dizer que essa seria uma interface comum escrita em Java. Aquela anotação diz que essa interface permitirá acesso a uma referência de um session bean que reside na mesma máquina que o container web. Caso precisássemos de acesso remoto, bastaria anotar a interface com @Remote para termos acesso a um enterprise bean residente em outro servidor.

Vamos agora implementar a interface Repositorio em uma classe RepositorioDeClientes:


@Stateless
public class RepositorioDeClientes implements Repositorio<Cliente> {

    @PersistenceContext()
    private EntityManager entityManager;

    public List<Cliente> buscarTodos() {

        Query query = entityManager.createQuery("select c from Cliente c");
        return query.getResultList();

    }

    public void remove(Cliente object) {

            entityManager.remove(entityManager.merge(object));
    }

    public Cliente buscarPorID(int id) {

        Cliente cliente = entityManager.find(Cliente.class, id);
        return cliente;
    }

    public void add(Cliente object) {

            entityManager.persist(object);
    }

    public void update(Cliente object) {

            entityManager.merge(object);
    }
   
}

RepositorioDeClientes é uma classe POJO normal, transformada em um poderoso session bean sem estado através da anotação @Stateless. O container gerencia um pool de objetos RepositorioDeClientes para servir aos usuários de seus serviços - usuários dessa e de outras aplicações. Além disso, usamos o recurso de dependency injection com a anotação @PersistenceContext, que serve para injetar um objeto EntityManager, elemento JPA responsável em gerenciar o provider OR/M usado na camada de infra-estrutura.

JPA, através da interface EntityManager, gerencia as entidades marcadas com a anotação @Entity fornecendo serviços de  persistência para os objetos. Funciona como um "guarda-chuva" para os diversos providers de mapeamento objeto relacional existentes no mercado como TopLink e Hibernate (para o exemplo o provider utilizado foi o Hibernate).


Anotando a entidade cliente:

@Entity
@Table(name="CLIENTES")
public class Cliente implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="CLIENTE_ID", nullable=false)
    protected int clienteID;

    @Column(name="NOME", nullable=false)
    protected String nome = "";

    @Column(name="LOGIN", nullable=false)
    protected String login = "";

    @Column(name="EMAIL", nullable=true)
    protected String email = "";

    @Column(name="SENHA", nullable=false)
    protected String senha = "";

    @Column(name="TELEFONE", nullable=true)
    protected String telefone = "";

    @Embedded
    protected Endereco endereco;

    public Cliente() {
        this.endereco = new Endereco();
    }

    //getters, setters e outros métodos 
}

Várias anotações (como @Table, @ID e @Column) dão importantes informações ao JPA de como deve ser feito o mapeamento objeto-relacional de uma maneira fácil e segura. O mais interessante é que as anotações são ignoradas pela JVM fora do contexto do container EJB e do controlador de entidades JPA. Em outras palavras, podemos testar tudo sem a necessidade de um aparato complicado que certamente prejudicaria a testabilidade dos componentes (conceito caro para quem trabalha com TDD).

Com tudo isso pronto, poderíamos ter um servlet controlador com um código parecido com esse:

public class GerenciarClienteServlet extends HttpServlet {

    @EJB
    Repositorio repositorio;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
    

        Cliente cliente = new Cliente();

        RequestDispatcher rd = null;

        try {
  
            //validações excluídas para melhorar a legibilidade
            cliente.setNome(request.getParameter("nome"));
            cliente.setLogin(request.getParameter("login"));

            //dados de endereco
            cliente.getEndereco().setRua(request.getParameter("rua"));
            cliente.getEndereco().setBairro(request.getParameter("bairro"));
            cliente.getEndereco().setCidade(request.getParameter("cidade"));
            cliente.getEndereco().setEstado(request.getParameter("estado"));

            cliente.setSenha(request.getParameter("senha"));
            cliente.setTelefone(request.getParameter("fone"));
            cliente.setEmail(request.getParameter("email"));

            repositorio.add(cliente);

            request.setAttribute("cliente", cliente);
            request.setAttribute("mensagem", "Cliente cadastrado com sucesso!");

            rd = request.getRequestDispatcher("/cadastroCliente.jsp");
            rd.forward(request, response);

        } catch (Exception e) {
           //gero log, direciono para página de erro, etc
        }

    }

A anotação @EJB injeta uma instância de RepositorioDeClientes e passa a controlar o seu ciclo de vida, facilitando muito o trabalho do desenvolvedor. Quem fica responsável pela criação do objeto é o  próprio container, que também se encarrega de sua destruição. O container irá criar um pool de objetos para otimizar o desempenho da aplicação. É importante observar que um servlet compartilha a mesma instância com vários clientes e por isso não devemos injetar um session bean @Stateful pois esse manterá o estado do objeto entre todas as requisições. Como nosso EJB do exemplo é  anotado com @Stateless podemos injetá-lo sem problemas.

Concluindo, nessa breve introdução, vimos como é viável trabalhar com um design limpo (orientado ao domínio e utilizando POJOs) e utilizar os recursos oferecidos pelo EJB de maneira fácil e descomplicada. A maior parte da "magia negra" do EJB é devida aos recursos oferecidos pelas anotações Java. Transformar uma classe em um poderoso enterprise bean apenas usando uma anotação @Stateless é simplesmente bom demais para ser ignorado.


Para saber mais: 

http://www.amazon.com/EJB-3-Action-Debu-Panda/dp/1933988347
http://www.amazon.com/Enterprise-JavaBeans-3-1-Andrew-Rubinger/dp/0596158025 (previsão 09/2010)

domingo, 25 de julho de 2010

OO, eu?

Mesmo uma linguagem orientada a objetos, como Java ou C#, pode ser utilizada, de forma consciente ou não, para criação de programas com base no paradigma estruturado. Nesse paradigma é grande a quantidade de estruturas de controle (como IF, IF-ELSE e SWITCH) e repetição (FOR, DO/WHILE). A pergunta que fica é: programas escritos utilizando orientação a objetos não precisam de tais estruturas? Como ficariam essas situações no código? Vejamos...

POO é sobre design. É o design da aplicação que determina se ela está aderente à metodologia estruturada ou à metodologia de objetos.

É claro que mesmo nas aplicações OO sempre haverá a necessidade de seleções e decisões. A diferença está na forma e na quantidade que tais elementos aparecem. Utilizando polimorfismo, um método que receba um parâmetro do super-tipo, por exemplo, não precisará de teste condicional, pois a implementação concreta será decidida somente no momento da passagem do objeto.

Observe (em C#):

    //uma Classe qualquer
    public void CalcularSalarioFuncionario(Funcionario funcionario)
    {
        //Gerente ou Vendedor? Só na hora será decidido.
        decimal valor = funcionario.CalcularSalario();

        //continuacao do método
    }

Um bom design OO diminui a necessidade de estruturas condicionais e de controle, porém não a elimina por completo. O fato é que isso (a eliminação) não é necessário para se obter um bom design, que seja robusto, de fácil manutenção e flexível.

Ex: Repositorio (em Java)

    //Classe RepositorioDePedidos
    public List buscarPedidosPorClienteID(int clienteID) {

     List pedidosDoCliente = new ArrayList();

     if (pedidos !=null) {

           for (Pedido pedido : pedidos) {   

                
                 Cliente cliente = pedido.getCliente();            
     
                 //aqui seria melhor usar o método equals() sobrescrito
                 if (cliente.getClienteID == clienteID) {
                      pedidosDoCliente.add(pedido);
                 }
           }
      }

      return pedidosDoCliente;
    }     



Repare que o método buscarPedidosPorClienteID tem elementos de decisão, seleção e controle. Tal situação ocorre a todo momento dentro dos repositórios.


E como poderia ser um cliente desse repositório?


    //uma Classe de controle qualquer
    public void gerarListaDePedidos(int clienteID)
    {
        RepositorioDePedidos repositorio = new RepositorioDePedidos();

        List pedidos = repositorio.buscarPedidosPorClienteID(clienteID);

        //renderizo uma tela, gero um relatorio, etc
    }  



O consumidor da classe RepositorioDePedidos  dispõe de uma API útil para buscar pedidos de um determinado cliente, dado o seu ID. Ele não sabe como o método funciona (encapsulamento), sabe apenas que funciona. A classe é reutilizável (várias instâncias podem ser criadas), fortemente tipada (somente o tipo Pedido) e tem detalhes de implementação desconhecidos (classe concreta ArrayList).

Com essas características não temos dúvida que o código de exemplo é OO, mesmo com a presença de elementos fundamentais de programação.

Um bom design OO diminui a necessidade de estruturas condicionais e de controle. Patterns, polimorfismo e outras técnicas podem ser utilizadas para tornar o código melhor escrito.

Mais informações sobre sobre estruturas de controle em programas aqui.

quarta-feira, 14 de julho de 2010

Arquitetura para o DDD

Continuando a série sobre o Domain Driven Design iniciada aqui, vamos agora comentar sobre como arquitetar as camadas da aplicação de modo a utilizar um Domain Model rico como a "base" do desenvolvimento.

Antes de mais nada, convém salientar que essa não deve ser vista como a única arquitetura que existe e que irá atender a todos os sistemas e situações do mercado. Trata-se apenas da arquitetura mais adequada a um projeto que trabalhe sob as premissas do DDD.

As camadas são representadas como abaixo:




Explicação sobre as camadas:



É importante dizer que não considero a camada Application como mandatória; ela é criada apenas se realmente adicionar valor à aplicação. Como a camada Domain é bastante rica em funcionalidades, muitas vezes não é necessário implementar mais essa divisão.

A criação de um Domain Model  traz uma série de vantagens para aplicações de larga escala e/ou complexas. Como bem disse Martin Fowler em PoEAA: "se você utilizar DDD para um projeto, você provavelmente irá cogitar utilizar a mesma técnica para outros (mesmo para os pequenos)."

Um design focado na criação de um Domain Model tem melhor manutenção no longo prazo devido à clareza da relação entre o negócio e a implementação. Além disso, é uma importante ferramenta para evitar a duplicação de código. Também aumenta a testabilidade do sistema.


quarta-feira, 23 de junho de 2010

Pesquisa Agile.

Laurie Williams, uma professora da North Carolina State University, vem conduzindo uma pesquisa para descobrir quais as práticas e os princípios que são mais utilizados pelas equipes ágeis.

A pesquisadora também convida os participantes a repensarem os princípios e práticas, propondo sugestões de melhoria (quando aplicável). 


Vejam os cinco princípios considerados mais importantes até o momento:
  1. Our highest priority is to satisfy the customer through early and continuous delivery of valuable software.
  2. Working software is the primary measure of progress.
  3. Deliver working software frequently, from a couple of weeks to a couple of months, with a preference to the shorter timescale.
  4. Build projects around motivated individuals. Give them the environment and support they need, and trust them to get the job done.
  5. At regular intervals, the team reflects on how to become more effective, then tunes and adjusts its behavior accordingly.

E as cinco práticas mais importantes:
  1. Short iterations (30 days or less)
  2. Continuous integration
  3. “Done” criteria
  4. Automated tests are run with each build
  5. Automated unit testing

Você pode conferir as atualizações da pesquisa aqui.

Caso queira participar da pesquisa é só vir aqui.

terça-feira, 15 de junho de 2010

Toque do Gênio


Na última segunda-feira, estive no seminário da PUC - Design de Software para o século XXI. A palestra principal era de Martin Fowler, um nome que dispensa apresentações. Basta dizer que a maioria dos livros de desenvolvimento de software dos últimos dez anos cita, em alguma medida, seu nome e referencia seu vasto trabalho em áreas como enterprise patterns, agile, TDD, Refactoring, UML e, mais recentemente, Domain Specific Languages (DSLs).


A primeira parte da palestra foi focada em discutir as DSLs, que é o tema de seu último livro (provavelmente sairá em outubro, segundo ele mesmo). Ele mostrou com podemos criar linguagens específicas a um determinado domínio, desmistificando o tema ao provar que estamos diariamente expostos a coisas semelhantes, tais como SQL, Linq, Struts e Hibernate. Esses são alguns exemplos, não de DSLs, mas de algumas ferramentas e linguagens dedicadas a resolver um único propósito. Por outro lado, Java e C# são o que ele chama de general programming languages, usadas para resolver qualquer tipo de problema e em qualquer domínio. O assunto foi quente e deixou a platéia com gostinho de "quero mais". É claro que irei encomendar o livro. -:)

A segunda parte foi mais árida e dedicada a falar sobre REST. Foi uma palestra MUITO técnica (algumas pessoas não faziam a menor ideia do que se tratava) e um pouco cansativa. Ele explicou os quatro níveis de arquitetura REST (0, 1, 2 e 3) e comentou os fundamentos de cada parte. Confesso que pelo que foi explicado, o que implementei até hoje pode ser classificado no máximo como nível 1. Estou precisando "comer um pouco mais de feijão" nesse assunto hehe.

A terceira parte da apresentação foi bem interessante e divertida. Martin mostrou os benefícios da integração contínua e da automação de builds e testes. Nessa parte ele já estava bem à vontade com a platéia e presenteou a todos com seu humor fino e colocações pertinentes. É muito inspirador vermos que podemos chegar a um nível tal de automação que nos permita entregar software para produção em intervalos cada vez mais curtos, podendo até ser diários. Ele comentou brevemente sobre o Cruise, que é uma ferramenta de CI da ThoughtWorks (com versão free, vale à pena verificar).

Por último, Martin abriu para perguntas e respondeu prontamente a todos que tinham questões.

E então, como última pergunta, um iluminado da platéia perguntou ao Martin se ele voaria em um avião que tivesse sido construído utilizando métodos ágeis. Ele calmamente respondeu que temos que, gradativamente, encontrar quais são as fronteiras do desenvolvimento ágil, simplesmente testando os seus limites (obviamente sem colocar a vida de ninguém em risco). Métodos ágeis ganham mais espaço em todo o tipo de projeto e assim tem sido diariamente ao redor do globo. Completou dizendo que não sabia o suficiente sobre aviação para uma resposta mais acurada e terminou contando a seguinte piada:

"Um grupo de alunos havia construído um sistema para determinado avião. 

Perguntaram ao professor desses alunos: - mestre, o senhor viajaria nesse avião?

O professor disse: - viajaria com toda certeza e estaria 100% seguro.

- Mas como o senhor pode ter tanta certeza que o avião não iria cair?

O professor então respondeu: - ora meu caro, se meus alunos fizeram esse sistema, é óbvio que o avião nem irá sair do chão!"

hahahaha

Ele terminou com essa piada e o pessoal foi ao delírio.

Toque do gênio!
Related Posts with Thumbnails