Refatoração – Prática para Manter Qualidade

No nosso post anterior sobre XP falamos sobre as várias práticas que compõem a metodologia. Neste artigo abordaremos os detalhes da Refatoração. O termo “refatoração” vem do inglês “refactoring”, e surgiu nas comunidades de Smalltalk nos anos 80/90. Foi inserida na indústria por Kent Beck como prática XP. Tornou-se famosa com o livro “Refatoração – Aperfeiçoando o Projeto de Código Existente” escrito por Martin Fowler. Segundo o próprio M. Fowler define:

“Refatoração é uma técnica disciplinada para reestruturar um código fonte existente, alterando sua estrutura interna sem mudar o seu comportamento externo. Sua essência está em uma série de pequenas transformações que preservam comportamento. Cada transformação (chamada de refatoração) faz pouca coisa, mas uma sequência de pequenas transformações produz uma reestruturação significativa. Uma vez que cada refatoração é pequena, é mais improvável que algo dê errado. O sistema se mantém funcionando integralmente após cada refatoração, reduzindo as chances de o sistema sofrer um dano grave durante a reestruturação”

O objetivo de refatorar um código freqüentemente é manter o custo de manutenção constante ao longo do tempo. Refatorações trazem simplicidade, flexibilidade, clareza e algumas vezes desempenho ao código. Elas ajudam a manter a casa em ordem. Sem refatorações o código tende a ficar cada vez mais bagunçado e quanto maior a bagunça, mais difícil é de arrumar, ou seja, bagunça tende a gerar mais bagunça, até o limite em que o código fica ilegível. O custo de manutenção fica tão alto que a única solução é jogar tudo fora e começar do zero (isso é a última coisa que queremos num projeto de software, embora algumas vezes seja necessária).

Vale lembrar que cada refatoração é um passo trivial (ovo de colombo). O segredo está em conhecer com maestria o vocabulário das refatorações e saber aplicar cada uma delas no momento certo. Martin Fowler mantém um catálogo online de refatorações. Alguns exemplos de refatorações:

  • Mudar o nome de uma variável
  • Encapsular um código repetido num método
  • Remover um parâmetro não utilizado em um método
  • Generalizar um método (ex: raizQuadrada(float x) => raiz(float x, int indice))

Por onde começar?

Antes de começar a aplicar refatorações, é importante que seu código já tenha uma boa base de testes automatizados. Teste é uma outra importante prática da metodologia XP. Testes e refatorações são práticas irmãs. Uma refatoração pode ocasionalmente inserir um erro no sistema. Os testes ajudarão a detectar e corrigir esses erros.

Após aplicar uma refatoração você irá rodar todos os testes “apertando um botão” e terá como resultado uma luz verde (testes passaram) ou uma luz vermelha (testes não passaram).

Um pequeno exemplo

Vamos dar um pequeno exemplo de refatoração para tornar o conceito claro. Alguns outros exemplos podem ser obtidos nesses slides e no catálogo online do Martin Fowler.

O nome da refatoração que vamos usar é Substituir Variável Temporária por Busca. suponha que uma variável local está sendo usada para guardar o resultado de uma expressão. A idéia desta refatoração é trocar as referências a esta expressão por um método. Variáveis temporárias encorajam métodos longos (devido ao escopo). Com a refatoração, o código fica mais limpo e o método pode ser usado em outros locais.

Os passos para essa refatoração são:

  1. Encontre variáveis locais que são atribuídas uma única vez
  2. Declare temp como final
  3. Compile (para ter certeza)
  4. Extraia a expressão
  5. Compile e teste

Exemplo de código:

double getPreco() {
    int precoBase = _quantidade * _precoItem;
    double fatorDesconto;
    if (precoBase > 1000) fatorDesconto = 0.95;
    else fatorDesconto = 0.98;
    return precoBase * fatorDesconto;
}



double getPreco() {
    final int precoBase = _quantidade * _precoItem;
    final double fatorDesconto;
    if (precoBase > 1000) fatorDesconto = 0.95;
    else fatorDesconto = 0.98;
    return precoBase * fatorDesconto;
}



double getPreco() {
    final int precoBase = precoBase();
    final double fatorDesconto;
    if (precoBase > 1000) fatorDesconto = 0.95;
    else fatorDesconto = 0.98;
    return precoBase * fatorDesconto;
}

private int precoBase() {
    return _quantidade * _precoItem;
}



double getPreco() {
    final double fatorDesconto;
    if (precoBase() > 1000) fatorDesconto = 0.95;
    else fatorDesconto = 0.98;
    return precoBase() * fatorDesconto;
}

private int precoBase() {
    return _quantidade * _precoItem;
}



double getPreco() {
    final double fatorDesconto = fatorDesconto();
    return precoBase() * fatorDesconto;
}

private int fatorDesconto() {
    if (precoBase() > 1000)
    return 0.95;
    return 0.98;
}

private int precoBase() {
    return _quantidade * _precoItem;
}

double getPreco() {
    return precoBase() * fatorDesconto();
}



double getPreco() {
    return precoBase() * fatorDesconto();
}

private int fatorDesconto() {
    if (precoBase() > 1000)
    return 0.95;
    return 0.98;
}

private int precoBase() {
    return _quantidade * _precoItem;
}

double getPreco() {
    return precoBase() * fatorDesconto();
}


Conclusões

O uso de refatorações se torna mais e mais freqüente na medida em que o programador vai ficando mais experiente. As refatorações não devem ser usadas de qualquer modo, mas sim no momento certo e no lugar certo. Um bom programador surge só com muito trabalho e experiência. Qualquer um pode escrever código que o computador consegue entender. Bons programadores escrevem código que pessoas conseguem entender.

Uma boa dica de quando refatorar é ao identificar três repetições no código. Outro indício é quando você está tendo necessidade de escrever comentários para explicar o que um código faz. Algumas ferramentas como o Eclipse e o Visual Studio já possuem atalhos para as refatorações mais comuns como renomear método, extrair superclasse, introduzir objeto parâmetro. A experiência em refatorações trará grandes melhorias na qualidade do código de um programador. Em breve falaremos mais sobre Testes (automatizados), mais uma importante prática em que a Programação Extrema se baseia.

Exibir ComentáriosOcultar Comentários