Mostrarei agora um pouco sobre refatoração de códigos, esse nome bonitinho que talvez seja "aportuguesado", não sei, mas que em linhas gerais trata-se de editar o código.
Claro que é só um pequeno artigo, nada a se comparar a livros como : Refatoração: Aperfeiçoando o Design de Códigos Existentes - Martin Fowler, mas da pra ser um pontapé inicial.
A Refatoração de código é uma prática essencial em desenvolvimento de software, que consiste em reorganizar o código existente para torná-lo mais legível, mantível e eficiente, sem alterar seu comportamento externo. Neste artigo, exploraremos os conceitos básicos de refatoração de código, seus benefícios e algumas técnicas comuns que você pode usar em seu código Python.
Por que refatorar o código?
O código que funciona pode não ser necessariamente bom código. À medida que um projeto cresce e se desenvolve, o código pode se tornar confuso, difícil de entender e difícil de manter. Algumas razões para refatorar seu código incluem:
Legibilidade: Um código mais legível é mais fácil de entender e, portanto, mais fácil de manter e aprimorar. Isso também pode melhorar a colaboração em equipe.
Manutenção: O código bem organizado é mais fácil de manter e modificar. Isso também reduz o tempo necessário para solucionar problemas ou corrigir erros.
Performance: Uma refatoração bem-sucedida pode melhorar o desempenho do código, tornando-o mais rápido e eficiente.
Escalabilidade: O código refatorado pode tornar o aplicativo mais escalável, preparando-o para lidar com cargas de trabalho maiores ou situações mais complexas.
Técnicas de refatoração
A refatoração pode assumir muitas formas diferentes e é influenciada pela estrutura do seu código. No entanto, existem algumas técnicas comuns que podem ser usadas para melhorar a qualidade do código Python.
Extração de método
A extração de método é uma técnica usada para dividir uma função grande em funções menores, que fazem parte do mesmo processo. Isso melhora a legibilidade do código e o torna mais modular.
Por exemplo, considere a seguinte função:
def calcular_pagamento(horas_trabalhadas, taxa_hora):
salario_bruto = horas_trabalhadas * taxa_hora
imposto_renda = salario_bruto * 0.20
salario_liquido = salario_bruto - imposto_renda
return salario_liquido
Esta função realiza vários cálculos em uma única função. Podemos usar a extração de método para dividir esses cálculos em funções separadas:
def calcular_pagamento(horas_trabalhadas, taxa_hora):
salario_bruto = calcular_salario_bruto(horas_trabalhadas, taxa_hora)
imposto_renda = calcular_imposto_renda(salario_bruto)
salario_liquido = calcular_salario_liquido(salario_bruto, imposto_renda)
return salario_liquido
def calcular_salario_bruto(horas_trabalhadas, taxa_hora):
return horas_trabalhadas * taxa_hora
def calcular_imposto_renda(salario_bruto):
return salario_bruto * 0.20
def calcular_salario_liquido(salario_bruto, imposto_renda):
return salario_bruto - imposto_renda
Observe que agora a função calcular_pagamento
chama outras três funções, cada uma com uma responsabilidade clara. Isso torna a função principal mais fácil de ler e entender.
Eliminação de duplicação
Duplicação de código é quando há trechos de código muito semelhantes em diferentes lugares do seu projeto. Isso pode levar a erros quando o código é atualizado em apenas um lugar e não em outros. Além disso, duplicação de código pode tornar o código mais difícil de manter.
Por exemplo, imagine que você tenha duas funções que calculam a área de um retângulo e de um círculo, respectivamente:
def calcular_area_retangulo(base, altura):
area = base * altura
return area
def calcular_area_circulo(raio):
area = 3.14 * raio ** 2
return area
Observe que a variável area
é calculada da mesma maneira nas duas funções. Podemos eliminar a duplicação de código criando uma função separada para calcular a área:
def calcular_area_retangulo(base, altura):
area = calcular_area_retangulo(base, altura)
return area
def calcular_area_circulo(raio):
area = calcular_area_circulo(raio)
return area
def calcular_area_forma_geometrica(base, altura=None, raio=None):
if raio:
area = 3.14 * raio ** 2
else:
area = base * altura
return area
Agora, ambas as funções calcular_area_retangulo
e calcular_area_circulo
chamam a função calcular_area_forma_geometrica
, que realiza o cálculo da área com base nos parâmetros fornecidos. Isso reduz a duplicação de código e torna o código mais fácil de manter.
Substituição condicional por polimorfismo
Substituição condicional por polimorfismo é uma técnica que envolve a criação de uma hierarquia de classes para lidar com situações em que um código é executado de maneiras diferentes com base em uma condição. Em vez de usar várias declarações if-else
, o polimorfismo usa a substituição dinâmica de métodos para lidar com diferentes casos.
Por exemplo, considere a seguinte função que verifica se um número é positivo, negativo ou zero:
def verificar_sinal_numero(numero):
if numero > 0:
return 'positivo'
elif numero < 0:
return 'negativo'
else:
return 'zero'
Essa função usa uma declaração if-else
para determinar o sinal do número. Em vez disso, podemos criar uma hierarquia de classes, uma para cada caso (positivo, negativo e zero), que contém um método para retornar a mensagem de texto:
class NumeroPositivo:
@staticmethod
def mensagem():
return 'positivo'
class NumeroNegativo:
@staticmethod
def mensagem():
return 'negativo'
class NumeroZero:
@staticmethod
def mensagem():
return 'zero'
def verificar_sinal_numero(numero):
if numero > 0:
return NumeroPositivo().mensagem()
elif numero < 0:
return NumeroNegativo().mensagem()
else:
return NumeroZero().mensagem()
Agora, a função verificar_sinal_numero
cria uma instância da classe correspondente com base no sinal do número e chama o método mensagem
. Isso permite que o código seja mais modular e fácil de estender. Se precisarmos adicionar suporte para números complexos, por exemplo, podemos criar uma nova classe e adicionar um novo caso à função verificar_sinal_numero
sem precisar modificar o código existente.
Simplificação de expressões booleanas
Expressões booleanas complexas podem ser difíceis de entender e de depurar. Ao simplificar essas expressões, tornamos o código mais legível e menos suscetível a erros.
Por exemplo, considere a seguinte expressão booleana:
if a and (b or not c) and (not b or d):
# faça alguma coisa
Podemos simplificar essa expressão usando identidades booleanas:
if a and (not c or d):
# faça alguma coisa
Isso torna a expressão mais fácil de ler e entender.
Extração de métodos
Quando um método de uma classe começa a ficar muito grande ou complexo, é uma boa prática extrair partes dele em novos métodos separados. Isso torna o código mais fácil de ler e entender.
Por exemplo, considere a seguinte classe que converte uma data em uma string no formato "dd/mm/aaaa":
class ConversorData:
def __init__(self, dia, mes, ano):
self.dia = dia
self.mes = mes
self.ano = ano
def converter_para_string(self):
resultado = str(self.dia) + '/'
if self.mes < 10:
resultado += '0'
resultado += str(self.mes) + '/'
resultado += str(self.ano)
return resultado
Podemos extrair o código que formata o mês em um método separado:
class ConversorData:
def __init__(self, dia, mes, ano):
self.dia = dia
self.mes = mes
self.ano = ano
def converter_para_string(self):
resultado = str(self.dia) + '/'
resultado += self.formatar_mes() + '/'
resultado += str(self.ano)
return resultado
def formatar_mes(self):
if self.mes < 10:
return '0' + str(self.mes)
else:
return str(self.mes)
Agora, o código que formata o mês está em um método separado, tornando a classe mais fácil de ler e entender.
Conclusão
No entanto, é importante lembrar que a refatoração deve ser usada com moderação. Refatorar um código que está funcionando pode introduzir novos bugs e consumir tempo e recursos desnecessários. A refatoração deve ser usada principalmente para melhorar a qualidade do código quando novos recursos precisam ser adicionados, ou quando o código se torna difícil de manter.
Além disso, é importante ter testes automatizados para garantir que as mudanças feitas durante a refatoração não afetem o comportamento do sistema. Esses testes devem ser executados regularmente durante o processo de refatoração para garantir que o código ainda está funcionando corretamente.
Em resumo, a refatoração é uma prática importante no desenvolvimento de software que nos permite melhorar a qualidade do código e reduzir a probabilidade de erros. Com as técnicas certas em mãos e com uma abordagem cuidadosa, podemos refatorar nossos códigos de maneira segura e eficaz.