O termo “refatorar” diz respeito à técnica de reestruturação de um trecho de código existente, modificando a sua estrutura interna sem modificar seu comportamento externo. Apesar de não parecer muito atraente para pessoas da área de gerência, a aplicação contínua desta prática poderá gerar efeitos bastante significativos na agilidade de trabalho do projeto alvo.
O que é
No livro “Refactoring”, escrito por Martin Fowler em 2000, ele define:
Substantivo:
“uma mudança feita na estrutura interna do software para deixá-lo mais fácil de entender e mais barato de modificá-lo, sem alterar seu comportamento observável.”
Verbo:
reestruturar um software aplicando uma série de refatorações, sem alterar seu comportamento observável.
Refatoração não é somente uma nova palavra para “limpar seu código”, pois define uma técnica de aprimoramento da saúde da base de código. Esta técnica consiste em aplicar várias transformações pequenas, com poucas alterações. Após várias dessas transformações em sequência o resultado final certamente será significativo.
Por que utilizar?
As intenções por trás da refatoração são: melhorar o design do código, melhorar a estruturação, reduzir complexidades, aplicar boas práticas, etc.
A refatoração é geralmente iniciada após a percepção de bad smells, ou seja, funções muito grandes, exagero de condicionais, identificação de códigos similares próximos, entre outros.
Outro ponto muito importante sobre a refatoração é a diminuição do custo para implementação de melhorias. Quando um software é lançado, existe a necessidade de continuar aprimorando-o constantemente, para correção de bugs e inclusão de novos recursos.
Numa base de código não saudável, a medida em que novos recursos vão sendo implementados, sem aplicação de refatoração, a velocidade do time de desenvolvimento irá diminuir constantemente. Por isso é importante manter a cultura de refatoração, para evitar o aumento de complexidade desnecessário.
Quando refatorar?
Segundo o livro, a refatoração não deve ser uma tarefa especial lançada no planejamento, mas sim uma prática inserida no dia-a-dia de todos os desenvolvedores. O autor ainda cita dois exemplos sobre o mindset que utiliza para definir quando um código precisa ser refatorado:
Ao adicionar um novo recurso a um sistema
Primeiramente, é necessário olhar ao código já existente e se ele está estruturado de um jeito que seja simples incluir essa nova funcionalidade. Se não estiver, geralmente é melhor aplicar refatorações no código antes, para que a inclusão do recurso seja feita de forma simples.
Assim o tempo total de sua tarefa deverá ser menor do que gastar horas tentando entender um código complexo e que, na próxima vez que um desenvolvedor passar por ele, terá de gastar muito tempo também tentando entendê-lo.
Ao modificar um recurso já existente
É sempre bom vasculhar a base de código já existente antes de começar. Pode ser que você encontre o que precisa em funções já definidas em outras partes do código, sobrando para você apenas o trabalho de chamá-las corretamente e evitar violar o princípio DRY.
Caso o código que você precise alterar exija bastante esforço para compreensão, então é melhor aplicar refatorações para que outro desenvolvedor não seja exigido novamente por esse código (incluindo seu “eu” do futuro).
Exemplos
A seguir, alguns exemplos de técnicas de refatoração presentes no livro:
Extract method
Problema: Você possui um fragmento de código que pode ser agrupado:
|
|
Solução: Agrupe este trecho em um novo método e chame-o no método antigo:
|
|
Esta técnica visa deixar seu código mais legível e reduzir a quantidade de linhas por método no código.
Extract variable
Problema: Você possui uma expressão difícil de entender:
|
|
Solução: Atribuir o resultado das expressões a variáveis cujo nome são auto-explicativos:
|
|
Esta outra técnica também visa aprimorar a legibilidade do código e reduzir a margem de erro ao lidar com múltiplas expressões.
Replace temp with query
Problema: Você criou uma variável temporária para receber o valor de uma expressão:
|
|
Solução: Mova a expressão para um método novo e utilize o retorno deste método:
|
|
Esta técnica é utilizada para deixar o código mais flexível e preparar o terreno para aplicar a Extract Method posteriormente.
Consolidate conditional expression
Problema: Você possui múltiplas condições que geram o mesmo resultado:
|
|
Solução: Consolide as condicionais em uma expressão única:
|
|
Assim você certamente irá evitar (ou até remover) trechos de códigos duplicados e possuir métodos simples para manutenções posteriores.
Decompose conditional
Problema: Você possui uma condicional complexa:
|
|
Solução: Decomponha as partes complexas em métodos separados: a condição, o trecho executado quando a condição for positiva e o trecho executado quando for negativa:
|
|
Assim é possível dividir lógicas complexas, de forma que seja possível esquecer o que ocorre no else
enquanto você estiver ocupado com o que deve ser executado dentro bloco if
.
Replace error code with Exception
Problema: Um método retorna um valor específico para indicar erro:
|
|
Solução: Lance uma exceção:
|
|
Lançar códigos de erros é algo obsoleto, herdado de linguagens procedurais. Lançar exceções irá lhe fornecer diagnósticos mais completos sobre as eventuais falhas ocorridas no sistema.
Conclusão
Neste artigo pudemos introduzir alguns tópicos sobre o assunto “refatoração” e exemplificar algumas técnicas básicas. Um mergulho nos materiais originais irá expandir seu repertório de técnicas de escrita de código, que podem ser bem úteis em situações extremas, ou seja, te tornará um desenvolvedor mais seguro e capaz.