sábado, 26 de março de 2011

A preguiça, o medo e o otimismo.


Somos seres humanos, logo somos cheios de "defeitos de fabricação". Disso quase ninguém duvida. Está programado no nosso DNA, fruto de anos e anos de evolução e seleção natural. Por isso, somos capazes de fazer coisas boas e ruins ao mesmo tempo. Ironicamente, é esse mix de defeitos e qualidades que nos torna únicos e molda a nossa humanidade, fazendo com que  sejamos, por exemplo, mesquinhos e solidários, egoístas e amorosos, medrosos e companheiros,  invejosos e prestativos, e por aí vai...

É óbvio gostamos de nossos amigos e familiares exatamente da forma como são, com todo o conjunto de imperfeições e qualidades que possuem e é por isso que perdoamos os seus pequenos  "desvios de comportamento" (ok, ok, sei que às vezes não são tão pequenos assim). Entretanto, quando o assunto é trabalho, as coisas precisam ser diferentes. Acredito que para alcançar a excelência, um profissional (e não apenas de software) precisa monitorar 3 vícios de comportamento; são eles: a preguiça, o medo e o otimismo.

A Preguiça

Qual ferramenta devemos usar sempre? Java ou .Net? Linux ou Windows? Que padrão podemos utilizar em todos os projetos? Vamos trabalhar de forma ágil ou tradicional? A equipe irá trabalhar com SCRUM ou com o guia PMBOK embaixo do braço? Essas (e outras) questões são corriqueiras nas rodas de profissionais. Na verdade, é a manifestação da já famosa "preguiça mental". Nosso cérebro (preguiçoso) insiste na procura da "bala de prata", ou seja, uma maneira única e universal capaz de solucionar todos os problemas.

A explicação é simples: se encontramos uma maneira única para tratar todas as situações liberamos tempo e energia para outras tarefas mais interessantes, seja no trabalho ou fora dele. É por causa desse vício de comportamento que muitas soluções são descartadas de imediato, simplesmente por estarem "fora do padrão" ou por não respeitarem uma regra qualquer que deveria ser seguida à risca, não importando o contexto da situação no momento.

Monitore esse mau hábito constantemente. Saiba que geralmente há mais de uma solução para solucionar um mesmo problema. Estude diversos padrões, tecnologias e métodos. Posso ser fã de DDD mas isso não significa que irei utilizar a técnica em todos os projetos que terei que tocar ao longo da carreira. O mesmo acontece com o universo das metodologias: podemos trabalhar com métodos ágeis e aplicar outras metodologias ao mesmo tempo, obtendo assim resultados muito melhores e adaptados à realidade do negócio em que estamos inseridos. Preste atenção ao contexto, isso é o mais importante. Explore a diversidade.


O Medo

"Agile não presta, é só um modismo da garotada". "PMBOK só serve para aumentar a burocracia no projeto". "Vai usar .Net? Tá maluco!" Essas e outras pérolas são ouvidas diretamente no trabalho, na faculdade, nos fóruns e em outros eventos comuns de TI. É simplesmente o medo falando mais alto. A ciência já sabe: nós dominamos (e populamos) nosso planeta porque somos uma espécie medrosa. Por exemplo, se um antepassado das cavernas visse uma sombra remotamente parecida com um tigre ele não pensaria duas vezes: "daria no pé", mesmo que fosse apenas um coelho inofensivo. Qualquer eclipsezinho solar e todo mundo já se reunia chorando para pedir perdão pelo "fim do mundo" próximo.

Não se engane: esse instinto do "lute ou fuja" está em você, somos descendentes diretos desses medrosos que se multiplicaram aos montes porque são avessos a riscos já de berço.

Esse medo pode ser resumido em uma única palavra: ignorância. Temos medo daquilo que não conhecemos; achamos mais fácil repudiar qualquer fato novo potencialmente ameaçador (lembra do tigre?) do que analisar e estudar com calma a novidade que se apresenta. Lute contra isso! Não diga que métodos ágeis são ruins sem estudar sobre o assunto. Não critique o PMBOK sem entender o contexto e a proposta do PMI. Não acredite que ferramentas e tecnologias possam mandar nas pessoas, a ponto de determinar a qualidade de um design de software. O antídoto para enfrentar o medo é o conhecimento. Acostume-se a pensar "fora da caixa".

O Otimismo

Procuro levar a vida com leveza, otimismo e bom humor. Quem me conhece sabe. Porém, ser otimista demais em projetos de desenvolvimento é arriscado. Sistemas são complexos e imprevisíveis, pequenas mudanças geralmente ocasionam consequências impossíveis de serem previstas em plenitude. Prazos se perdem facilmente se a equipe não olhar de perto problemas e obstáculos.  Programas se tornam incompiláveis se não houver preocupação constante com merges e commits. A "lei de Murphy" é a regra, não a exceção em projetos. Por isso, uma atitude mais defensiva é sempre desejável.

Acredite, o seu componente de software não irá funcionar só porque você deseja que funcione. Os riscos não irão deixá-lo em paz só porque você está fazendo "pensamento positivo" ou pensando que "o universo conspira a seu favor". O Cosmos não se interessa pelo seu projeto; é melhor deixar essas coisas de lado e se preparar para evitar que coisas ruins aconteçam de forma racional e isenta. É preciso ter um plano para se preparar para os obstáculos que invariavelmente invadem todos os projetos de sistemas.



Conclusão: vigie sua preguiça, controle seu medo e não seja demasiadamente otimista. Assim, irá se tornar um profissional muito mais produtivo, inteligente, flexível, inovador e responsável.

Tenho certeza que você irá se surpreender com os resultados.

Até a próxima!



segunda-feira, 22 de novembro de 2010

Ainda estou aqui, chefe...

Fala pessoal,

Update rápido só para a galera saber que ainda estou vivo hehe.

Estou com a agenda super atribulada e (obviamente) sem tempo para postar como eu gostaria por aqui. Tenho que dividir o tempo entre o trabalho na CETIP, as aulas no INFNET, os estudos e ainda (é lógico) dar a devida atenção para amigos e família. Não é fácil não...

Fiquem de olho no que está por vir:

- De 13 a 17 de Dezembro ocorre a Semana de Engenharia de Software no Infnet. Vou palestrar 2 dias sobre métodos ágeis e suas implicações para o futuro do desenvolvimento de software. Entrem no link do evento e chequem as datas.


- Tem artigo meu sendo publicado na próxima edição da Java Magazine (Ed 86). Faço uma comparação bem interessante entre dois patterns que uso bastante no dia a dia: SPECIFICATION [EVANS] e STRATEGY [GOF]. Vale dar uma conferida...


- Estou preparando um material bem legal sobre Agile e CMMI, fruto das minhas pesquisas na pós e embrião para os trabalhos de mestrado. Quem se interessar pelo assunto é só entrar em contato comigo por email ou aqui diretamente.


Grande abraço a todos e até breve.

sexta-feira, 3 de setembro de 2010

O que é SOA, afinal?


Um assunto um tanto delicado, ainda não debatido aqui no blog, é a respeito de SOA - Service Oriented Architecture. Tanto DDD quanto SOA são assuntos relativamente novos. Porém, enquanto o primeiro está bem definido e estabelecido na comunidade de desenvolvimento de software, o segundo ainda carece de alguns padrões que unifiquem as diferentes visões que existem sobre a técnica. Este post é o início da minha colaboração (meus 2 cents).


Definição

Definir SOA é complicado. A maioria das definições é baseada na ideia de sistemas compostos por serviços independentes. Entretanto, o que exatamente constitui um serviço não está claro. O que não resta dúvida é o fato de SOA ser uma forma arquitetural de se desenvolver software, forma guiada pela reutilização e compartilhamento entre aplicações e componentes. Nas palavras do mestre Udi Dahan:

Specifically, SOA deals with systems or applications that are, or can be, distributed. The acknowledgment that distribution is a primary architectural issue is one of the underlying currents of SOA.

O software que precisa rodar em um ambiente distribuído tem de ser projetado de forma diferenciada. As layers e tiers no mundo SOA são unificadas em "serviços", que são ao mesmo tempo unidades de design e de deployment. Enquanto que numa arquitetura tradicional  não há restrição em como essas camadas irão se comunicar, em SOA os serviços devem se comunicar de acordo com padrões de mensagens definidos por um schema (ou contrato).


O que é um Serviço?

Muito da literatura existente hoje foca em descrever propriedades (e princípios) dos serviços em vez de definir o que um serviço é de fato. Na essência, sabemos que a classe que implementa determinado serviço deve ser desacoplada dos clientes que evetivamente a consomem. Isso é bem diferente dos ambientes Java RMI, COM e .NET remoting, onde o cliente precisa explicitamente referenciar tipos específicos de plataforma. 

Vejamos então os princípios fundamentais de um serviço:

- Serviços são autônomos: autonomia significa a capacidade de se autogovernar, um serviço autônomo é aquele que independe de um elemento externo para executar sua lógica.

- Serviços têm fronteiras bem definidas: essa definição está lado a lado com o princípio da autonomia; torna claro onde um serviço termina e outro começa.

- Serviços abstraem a lógica: serviços devem ser tratados como uma caixa preta, assim como componentes de um sistema. Assim sendo, a programação neles inclusa pode ser substituída a qualquer momento, sem afetar aqueles que o consomem.

- Serviços expõem schema e contratos, não classes ou tipos: contratos são documentos textuais que descrevem o que o serviço faz, os padrões WSDL (Web Service Description Language), UDDI (Universal Description Discovery and Integration) e SOAP (Simple Object AccessProtocol) são muito utilizados no dia a dia.

- Serviços são reutilizáveis: um serviço reutilizável é aquele que não carrega particularidades técnicas de uma implementação ou regras de negócio específicas e é genérico o suficiente para atender outros projetos. 


OO e SOA

Segundo Udi Dahan, apesar de muitos terem previsto que SOA seria a próxima geração do desenvolvimento de aplicações - com a consequente substituição do padrão OO atual - nada  significativo realmente aconteceu. Na verdade, SOA e OO trabalham em diferentes (e complementares) níveis. OO lida com design e código de uma única deployment unit enquanto SOA lida com múltiplas deployment units. Dahan nos explica:

SOA does not suggest new or alternate ways of designing or coding the internal logic of a given application or service. There is no reason SOA and OO should not be  cooperative technologies.

Princípios fundamentais de OO como separation of concerns e dependency inversion estão presentes na construção de aplicações service oriented, tanto na arquitetura externa como na construção interna de seus serviços. SOA é complementado por OO; não é a evolução do OO. No entanto, podemos considerar SOA como a evolução da arquitetura distribuída de componentes.


Conclusão

Há vários anos que SOA é assunto nas rodas de TI. Apesar de haver muito barulho em torno do tema, não há dúvida de que é um conceito interessante e uma técnica atraente para construção de componentes (serviços) reutilizáveis. SOA e OO não são incompatíveis. Em muitos níveis OO fornece insights válidos para construção de serviços robustos e independentes de plataforma. Para os que se interessaram pelo tema, sugiro a leitura e pesquisa para atualização da visão atual da técnica, muita coisa têm mudado a respeito do tema nos últimos anos. Voltarei posteriormente com o assunto aqui no blog.


segunda-feira, 30 de agosto de 2010

Palestra na Rio Info 2010

Fala Pessoal,
Tudo bem?

Estarei fazendo uma oficina na Rio Info 2010, junto com meu amigo e mestre Armênio Cardoso, nessa próxima quarta-feira, dia 01/09/2010. Vamos abordar a construção de um aplicativo Java Mobile utilizando o Agile como pano de fundo.

Quem quiser ir na oficina me avise aqui no blog (ou por email) que eu envio a senha para efetivar o convite. Temos um limite de convidados que podemos chamar.

Cliquem aqui para saber mais sobre a oficina e sobre a Rio Info 2010.

Abraços,

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.
Related Posts with Thumbnails