Saturday, September 24, 2005

Refactoring

Dia desses, eu estava perdido na web, lendo sobre refactoring. Para quem está envolvido com desenvolvimento ágil, o vocábulo já paz parte do jargão diário e quem pratica XP provavelmente não consegue imaginar como existe gente que não usa a técnica deliberadamente.

O novato desavisado tende a reduzir tudo que escuta ao que lhe parece a essência da coisa, para simplificar e tentar entender o assunto. Falar em 'melhorar a estrutura do código sem modificar seu comportamento externo' pode parecer a este novato uma mera desculpa para ficar mimando o código, dando mais atenção a ele do que o estritamente necessário. Refatorar está, aparentemente, ligado a 'consertar o que não está quebrado'.

Aparentemente.

Na verdade, não tem nada a ver com isso. Refactoring é um dos processos que nos permite evitar ter todas as idéias sobre a arquitetura do sistema no início do desenvolvimento. Refactoring permite modificar o design do software segura e rapidamente quando necessário (e somente quando necessário). Com refactoring, podemos nos permitir aprender sobre o sistema ao mesmo tempo que o desenvolvemos. Não precisamos nos limitar a soluções pré-fabricadas (mas podemos fazer uso delas), muito menos projetar todo o sistema antes de começar a codificar.

Vantagens demais para ser verdade? Acho que não. Na verdade já fazemos isto todos os dias. Fazemos isto, por exemplo, quando identificamos uma lógica de execução comum para duas rotinas e dela extraímos uma terceira. Ou então quando movemos responsabilidades de uma classe para outra, como mostra Martin Fowler neste exemplo do seu 'Refactoring: Improving the design of existing code' (que já possui tradução para nosso querido idioma pátrio).

Digamos que foi feito um sistema para uma locadora de filmes (sim, Martin Fowler também tem seus momentos de baixa criatividade). Este sistema foi feito por uma equipe ainda não iniciada às artes do refactoring e que também não entendia muito de herança e polimorfismo na época. O cálculo de débito do cliente é calculado na classe Customer com auxílio do seguinte método privado, responsável pelo cálculo de débito proveniente de uma única locação.

class Customer {
  ...
  private double amountFor(Rental aRental) {
    double result = 0;
    switch (aRental.getMovie().getPriceCode()) {
      case Movie.REGULAR:
        result += 2;
        if (aRental.getDaysRented() > 2)
          result +=
            (aRental.getDaysRented() - 2) * 1.5;
          break;
      case Movie.NEW_RELEASE:
        result += aRental.getDaysRented() * 3;
        break;
      case Movie.CHILDRENS:
        result += 1.5;
        if (aRental.getDaysRented() > 3)
          result +=
            (aRental.getDaysRented() - 3) * 1.5;
        break;
    }
    return result;
  }      
  ...
}

Este método é utilizado por outro maior que calcula todo o débito do cliente. A equipe que desenvolveu o sistema original teve ao menos o cuidado de extrair este método para evitar que o maior ficasse exageradamente grande, mas não notaram que o novo método na verdade não pertence à classe Customer. Note que o método só mexe com atributos da classe Rental e pertence logicamente a ela. Podemos mover o método para ela e chamar apenas rental.getCharge() no local original sem perder o significado.

Depois disso, é hora de transformar esse switch altamente suscetível a erros em uma chamada de método da classe Movie, talvez utilizando o padrão State. Refactoring é a simples aplicação de modificações pequenas como estas de modo controlado. Acho que já deu pra pegar a idéia.

Talvez tenha alguém dizendo: "Mas isso não pode dar certo! As mudanças são pequenas demais para serem signiticativas."

Sim, as mudanças são pequenas. A força delas não vem da utilização isolada, mas contínua. Aqui o todo é maior do que a soma das partes, por causa da interação entre as várias mudanças.

Mas não nos limitemos a alguns exemplos. Fazer isso seria agir como o novato do qual falamos. Começar a aplicar refactoring na prática é tão fácil quanto não se limitar a duplicar um trecho de código deliberadamente, mas capturar a duplicação e escrever o caso geral. Isto pode se concretizar na extração de uma rotina, na identificação da oportunidade de usar um design pattern ou de muitos outros modos que vamos descobrindo quando tentamos.

Saturday, September 03, 2005

Desenvolvimento ágil e punk rock

Quem me conhece sabe que gosto um pouco de música e outro pouco de desenvolvimento de software. Por isso eu gosto de usar a música para entender o que acontece nesse mundo complicado cheio de aplicações, frameworks, sistemas e metodologias que é o mundo do software.

Quando os Ramones inventaram o punk rock lá pela década de 70, eles quiseram simplificar o rock 'n roll, aproveitando a experiência adquirida pela comunidade em 20 anos de história. Eles se perguntaram: 'Qual é a essência do rock por trás desses solos infindáveis e arranjos complicados?' e a resposta foi o trio baixo, guitarra e bateria e canções simples e curtas.

O que os autores do manifesto ágil e centenas de programadores (eu me arriscaria a dizer milhares) em todo o mundo fizeram foi bem parecido. Eles se perguntaram 'Qual é a essência do desenvolvimento de software por trás dessas inúmeras ferramentas e processos complicados?' e despiram a prática comum em busca das necessidades fundamentais. O interessante é que a maioria dessas necessidades podem ser supridas por práticas simples, desde que saibamos como e porquê utilizá-las.

O ser humano tem uma certa tendência a se acomodar. Quando estamos acostumados com alguma forma de trabalho, tendemos a acreditar que ela é 'A' solução. Até mesmo quando ainda não tivemos tempo de nos acostumar a nenhuma forma de trabalho, tendemos a aceitar a forma que parece a princípio mais 'séria'. E, para o explorador incauto, a 'seriedade' aqui quase sempre é sinônimo de formalidade.

Algumas pessoas acreditam que o punk rock talvez tenha ido longe demais na simplificação. Uma parte dessas pessoas estava acostumada demais com o 'rock antigo' para serem capazes de avaliar imparcialmente o novo movimento. A outra parte simplesmente não entendia a razão daquilo e preferia confiar no que parecia mais 'elaborado'.

Se você é um dos que acha que o desenvolvimento ágil é simples demais para funcionar, mas está intrigado por ouvir tanto falar nisso, os links nesse post são um bom ponto de partida. Boa sorte.