O que é Refatoração?

editar

Refatorar envolve modificar a estrutura interna de um código existente para melhorar sua qualidade, seja por meio de reescrita, realocação ou exclusão de elementos, mas sem alterar seu comportamento funcional.

A refatoração é um processo amplamente utilizado na área de desenvolvimento de software, sendo uma das práticas mais comuns na Metodologia Ágil, especialmente na Programação Extrema.

Por que Refatorar?

editar

Muitos profissionais da área desenvolvimento não adotam a prática da refatoração, pois a consideram desnecessária, uma vez que o código está funcionando como deveria. No entanto, o verdadeiro problema surge quando esse mesmo código precisa ser modificado de alguma forma, e sua qualidade prejudicada acaba dificultando ou atrasando esse processo, exigindo um investimento a mais de tempo apenas para entendê-lo.

Com isso podemos responder à pergunta: Por que refatorar?

A prática de refatoração embora às vezes possa parecer não trazer benefícios imediatos, ela nos garante à longo prazo:

  • Legibilidade : Códigos bem refatorados são geralmente mais concisos e fáceis de ler, facilitando seu entendimento em casos de modificações futuras;
  • Manutenção / Escalabilidade : Refatorar um código torna mais fácil a implementação de novas funcionalidades futuramente, devido muitas vezes ao item anterior, o que também nos garante uma maior facilidade na identificação de bugs e na manutenção dele;
  • Desempenho : Algumas das técnicas existentes de refatoração (Otimizar um algoritmo por exemplo) permitem um aumento no desempenho do código, tornando- o mais eficiente;

Quando Refatorar

editar

Saber quando refatorar é crucial para garantir a eficácia e o sucesso desse processo no desenvolvimento de software. Idealmente, como prática do XP, a refatoração deve ser realizada regularmente durante o processo de desenvolvimento, toda vez que um código é modificado ou incrementado, e sempre utilizando um bom conjunto de testes para garantir que nenhuma mudança funcional ocorreu, mantendo assim uma boa qualidade até o produto final.

Em condições gerais, a realização da refatoração poderá ser útil ao se deparar com:

  • "Code Smells" : Esse termo do inglês também utilizado no contexto da Metodologia Ágil se refere à alguns indícios de que o código-fonte não foi muito bem projetado, como por exemplo a presença dos chamados "código espaguete", presença de trechos de código duplicados, assim como outras práticas negativas que foram utilizadas durante o desenvolvimento, resultando em um código muitas vezes desnecessariamente complexo e de difícil entendimento;
  • Adição de novas funcionalidades: Muitas vezes é mais prático refatorar um código antes de simplesmente implementar uma nova funcionalidade, pois a refatoração pode facilitar e acelerar esse processo ao ajudar no entendimento e modificação do código ;
  • Correção de Bugs : Assim como na adição de funcionalidades, a correção de bugs pode ser muito beneficiada pela refatoração, pois uma melhora na legibilidade do código facilita a identificação e correção de bugs existentes.

Exemplos

editar

O ato de refatorar consiste em alguns passos simples:

1- Definir o quê será refatorado;

2- Identificar quais técnicas utilizar e onde utilizar;

3- Realizar as refatorações;

4- Rodar os testes para garantir que nenhuma funcionalidade foi alterada;

E seguindo isso, podemos ilustrar alguns exemplos ao mesmo tempo que exemplificamos algumas das técnicas de refatoração existentes:

Renomeação de Variáveis

editar
double IMC (double p, double a) {
    double i = (p/(a*a));
    return i;
}

Nesse exemplo, as variáveis "p" e "a" são pouco intuitivas, dificultando a compreensão da função IMC e de quais parâmetros utilizar ao chamá-la. Ao renomear essas variáveis para algo mais descritivo, como "peso" e "altura", tornamos o código mais claro e de fácil utilização.

double IMC (double peso, double altura) {
    double imc = (peso/(altura*altura));
    return imc; 
}

Substituição de números mágicos

editar
double calcula_total (int quantidade) {
    double total = quantidade * 1.8;
    return total;
}

Nesse exemplo, "1.8" é o nosso número mágico, pois da forma apresentada, apenas quem escreveu a função sabe de fato o que ele significa. Ao declarar uma constante para esse número PRECO_UNIDADE, fica mais claro que o número se trata do preço unitário de algum produto e que nossa função está calculando o valor total de uma compra.

#define PRECO_UNIDADE 1.8

double calcula_total (int quantidade) {
    double total = quantidade * PRECO_UNIDADE;
    return total;
}

Extrair Função

editar
int passou_de_ano(double *notas, int qtd_alunos, double nota_aluno) {
    double media = 0;
    for (int i = 0; i < qtd_alunos; i++) {
        media += notas[i];
    }
    media = media/qtd_alunos;
    return (nota_aluno >= media);
}

Nesse exemplo temos uma função que verifica se um aluno passou de ano, ou seja, ficou acima da média da turma. Uma forma de deixar este código mais organizado seria utilizando a técnica de extrair função, onde a partir da função apresentada, criaríamos uma nova função que calcula a média da turma e manteríamos apenas a verificação desejada originalmente.

double calcula_media (double *notas, int qtd_alunos){
    double soma = 0;
    for (int i = 0; i < qtd_alunos; i++) {
        soma += notas[i];
    }
    return (soma/qtd_alunos);
}

int passou_de_ano(double *notas, int qtd_alunos, double nota_aluno) {
    double media = calcula_media(notas, qtd_alunos);

    return (nota_aluno >= media);
}

Substituir Algoritmo

editar
int ordenado(int *vetor, int tamanho) {
    int cont = 0;
    while (cont < tamanho - 1) {
        if (vetor[cont] > vetor[cont + 1]) return 0;
        cont++;
    }
    return 1;
}

void embaralha(int *vetor, int tamanho) {
    int i, temp, r;
    for (i = 0; i < tamanho; i++) {
        temp = vetor[i];
        r = rand() % tamanho;
        vetor[i] = vetor[r];
        vetor[r] = temp;
    }
}

void bogosort(int *vetor, int tamanho) {
    while (!ordenado(vetor, tamanho))
        embaralha(vetor, tamanho);
}

Nesse exemplo é implementado o algoritmo BogoSort para prováveis futuras ordenações, mas além de um pouco confuso, esse algoritmo é extremamente ineficiente. Para isso podemos alterar o algoritmo utilizado para um mais eficiente e conhecido como o BubbleSort.

void bubbleSort(int *vetor, int tamanho) {
    int i, j, temp;
    for (i = 0; i < tamanho - 1; i++) {
        for (j = 0; j < tamanho - i - 1; j++) {
            if (vetor[j] > vetor[j + 1]) {
                temp = vetor[j];
                vetor[j] = vetor[j + 1];
                vetor[j + 1] = temp;
            }
        }
    }
}

Conclusão

editar

Em resumo, a refatoração representa uma prática essencial no desenvolvimento de software, não apenas aprimorando a estética, mas também elevando a qualidade do código. Ao simplificar, reestruturar e otimizar o código-fonte, a refatoração não só torna o software mais legível e compreensível, como também contribui significativamente para a eficiência e a agilidade do projeto como um todo.

Referencias

editar

https://www.refactoring.com

https://pt.wikipedia.org/wiki/Refatoração

https://refactoring.guru/pt-br/refactoring/smells