Os 10 métodos indispensáveis para refatorar seu código

Como vimos, no artigo Introdução a Refatoração de Código, existem diversos métodos.

Neste artigo, iremos detalhar os principais métodos, propostos por Martin Fowler, bem como, a demonstração de exemplos práticos na linguagem C#.

1 – Extrair Método

Extrair método é uma das refatorações mais comuns. Sempre que tiver um método muito longo que realiza diversas atividades deverá refatora-lo.

Vejamos, no exemplo abaixo, um código que aplica o Extrair Método.

public void imprimirSaldo(int conta)
{
    //Imprime o cabeçalho
    Response. write("Saldo da conta do cliente" + conta);
    Response.write("Cliente VIP");

    //imprime detalhes
    Response.write("Nome: " + _nome);
    Response.write("Valor: " + _valor);
}

Com a aplicação do Extrair Método, teremos que remover parte do código do método imprimirSaldo e criar outros métodos que representem o que ele faz e posteriormente, fazer a chamada dos novos métodos.

public void imprimirSaldo(int conta)
{
    imprimirCabelhalho(conta);
    imprimirDetalhes();
}

public void imprimirCabecalho(int conta)
{
    Response.write("Saldo da conta do cliente: " + conta);
    Response.write("Cliente VIP");
}

public void imprimirDetalhes()
{
    Response.write("Nome: " + _nome);
    Response.write("Valor: " + _valor);
}

2 – Parametrizar Método

Diversos métodos fazem coisas semelhantes, mas com diferentes valores contidos no corpo do método. Vejamos o exemplo abaixo:

public class Empregado
{

    private double salario;

    public void aumentarSalFuncionario()
    {
        salario *= 1.1;
    }

    public void aumentarSalGerente()
    {
        salario *= 1.5;
    }
}

Nesse exemplo, temos dois métodos que fazem coisas semelhantes. Com a aplicação do Parametrizar Método, teremos apenas um método genérico.

public class Empregado
{

    private double salario;

    public void aumentarSalalario(double fator)
    {
        salario *= (1 + fator);
    }
}

3 – Extrair Classe

Na Orientação a Objetos é fundamental o conceito de abstração, mas na prática negligenciamos esse conceito, devido a falta de tempo para planejar e organizar as classes em um programa.

Vejamos, o exemplo abaixo para melhor entendermos a extração de classe.

public class Aluno()
{
    private String _nome;
    private String _matricula;
    private String _CPF;
    private String _DDD;
    private String _Celular;

    public String lerNumeroCelular(){
        return "(" + _DDD + ") " + _Celular;
    }

    public String nomeAluno(){
        return _nome;
    }
}

Com a aplicação do Extrair Classe, teremos a separação do que não pertence a classe Aluno para outra classe mais adequada.

public class Aluno()
{
    private String _nome;
    private String _matricula;
    private String _CPF;

    public String nomeAluno(){
        return _nome;
    }
}

public class Telefone()
{
    private String _DDD;
    private String _Celular;

    public String lerNumeroCelular()
    {
        return "(" + _DDD + ") " + _Celular;
    }
}

4 – Substituir Comando Condicional por Polimorfismo

Na Orientação a Objetos, o polimorfismo é um dos grandes conceitos existentes, que lhe traz a possibilidade de tipificar suas classes e com isso, estender sempre que surgirem novos tipos de objetos. Vejamos, o exemplo abaixo para melhor entendermos.

protected void btnMostrar_Click(object sender, EventArgs e)
       {
           switch (txtNome.Text)
           {
               case "Palmeiras":
                   lblResultado.Text = "É campeão!";
                   break;
               case "São Paulo":
                   lblResultado.Text = "3º Lugar";
                   break;
               case "Santa Cruz":
                   lblResultado.Text = "2º Lugar";
                   break;
               default:
                   lblResultado.Text = "Não encontrado";
                   break;
           }
       }

Com a aplicação do Substituir Comando Condicional por Polimorfismo, teremos a criação de uma classe Pai e diversas classes filhos.Vejamos, na Figura 01, o diagrama das classes para melhor entendermos.

Diagrama de Classes com Polimorfismo

Figura 01 – Diagrama de Classes com Polimorfismo

Observe que a classe Time tem um método abstrato e nas subclasses, esse método, foi sobrescrito.

5 – Encapsular Campo

Na Orientação a Objetos, os atributos de uma classe não são acessíveis diretamente.

public String _nome;

Devemos criar métodos que façam a atribuição e retorno de valor dos atributos de uma classe.

private String _nome;

public String getNome() { return this._nome;}

public void setNome(String nome) { this._nome = nome;}

Observe que o atributo _nome está com a visibilidade alterada para private e foram criados dois métodos getNome e setNome.

6 – Substituir Herança por Delegação

Devemos refatorar quando uma subclasse usa apenas parte da interface de uma superclasse ou não quer herdar dados. Vejamos, na Figura 02, o diagrama das classes para melhor entendermos.

Exemplo de subistituição de herança por delegação

Figura 02 – Exemplo de Substituição de Herança por Delegação

7 – Substituir Atributo por Objeto

Devemos refatorar sempre que tiver um atributo de uma classe que apresenta informações adicionais. Vejamos, no exemplo abaixo, um exemplo clássico de atributo com valores adicionais.

public class Pedido
{
    private String cliente;
    private int numeroPedido;

    public getNomeCliente(){
        return this._cliente;
    }
}

Com a aplicação do Substituir Atributo por Objeto, teremos a separação do que não pertence a classe Pedido para outra classe mais adequada.

public class Pedido
{
    private Cliente oCliente;
    private int numeroPedido;
}

public class Cliente
{
    private String _nome;

    public getNomeCliente(){
        return this._nome;
    }
}

Observemos que na classe Pedido apareceu um referência à classe Cliente.

8 – Substituir Vetor por Objeto

Quem nunca utilizou um vetor para armazenar informações distintas. Vejamos o exemplo abaixo.

string[] dados = new string[2];
dados[0] = txtLogin.Text;
dados[1] = txtSenha.Text;

txtMsg.Text = dados[0] + " " + dados[1];

Com a aplicação do Substituir Vetor por Objeto, teremos a criação de uma classe que melhor representará as informações contidas no vetor.

Usuario oUsuario = new Usuario();
oUsuario.setLogin(txtLogin.txt);
oUsuario.setSenha(txtSenha.txt);

txtMsg.Text = oUsuario.getLogin() + " " + oUsuario.getSenha();

9 – Introduzir Objeto Parâmetro

Sempre que iniciamos o desenvolvimento de uma aplicação utilizamos a passagem de parâmetros de forma aleatória para ganharmos tempo. Mas, com o passar do tempo vão surgindo a necessidade de adicionar novos parâmetros no método, então, começamos a pensar como resolver esse problema. Vejamos o exemplo abaixo.

public class Conta
    {
        double lerFluxoentre(DateTime inicio, DateTime fim)
        {
            double resultado = 0;
            //....Aqui vai a lógica
            return resultado;
        }        
    }

Observe que temos informações semelhantes como parâmetros distintos. Com a aplicação do Introduzir Objeto Parâmetro, teremos a criação de uma classe que melhor representará as informações contidas nos parâmetros e posteriormente, substitui-los.

public class FaixaData
{
    private DateTime _inicio;
    private DateTime _fim;

    public void FaixaData(DateTime inicio, DateTime fim)
    {
        this._inicio = inicio;
        this._fim = fim;
    }

    //...Acesso pelos métodos get e set
}

O introduzirmos o Objeto Parâmetro, o código da classe Conta terá o comportamento abaixo:

public class Conta
    {
        double lerFluxoentre(FaixaData data)
        {
            double resultado = 0;
            //....Aqui vai a lógica
            return resultado;
        }

        public void Teste()
        {
            DateTime _inicio= new DateTime(2016,5,31);
            DateTime _fim = new DateTime(2016,6,3);

            double fluxoJaneiro = lerFluxoentre(new FaixaData(_inicio,_fim));
        }
    }

Observe no método Teste que inicializamos a chamada do método lerFluxoentre com um objeto.

10 – Substituir Números Mágicos por Constantes Simbólicas

Reaproveitar é tudo na Orientação à Objetos. Nesse caso, teremos que encontrar os valores padrões e substituir por constantes. Vejamos o exemplo abaixo:

public double calcularComprimentoCircuferencia(double raio){
    return 2 * 3.1415 * raio;
}

No caso, o valor de PI poderá ser utilizado em outro local e teremos que repetir e caso esse valor possa sofrer alguma alteração, como mais casas decimais, ficará difícil controlar essa mudança.

public const double CONSTANTE_PI = 3.14159265358979323846;

public double calcularComprimentoCircuferencia(double raio)
{
    return 2 * CONSTANTE_PI * raio;
}

Conclusão

Como pudemos observar, os métodos de refatoração podem melhorar e muito o entendimento do código e facilitar a manutenção futura do mesmo. Pratique sempre que puder os conceitos de refatoração de código para torna-lo mais entendível por você e pelos outros desenvolvedores.

Fique à vontade para utilizar os comentários!

Até o próximo artigo.

Prof. Norton Guimarães
@nortoncg

Referências

FOWLER, Martin. Refatoração: aperfeiçoando o projeto do código existente. Porto Alegre: Bookman, 2004.

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *