Pontos Principais
-
O Refactoring é um livro para desenvolvedores relativamente novos aprenderem uma prática importante no caminho de se tornarem desenvolvedores eficazes, e um livro para ajudar os desenvolvedores seniores a ensinar essa prática;
-
A segunda edição carrega bastante da mensagem do livro anterior, mas é menos focada nos objetos, além de incluir exemplos em JavaScript, apesar do livro não estar vinculado a nenhuma linguagem específica;
-
Mesmo que seja necessário fazer alterações complexas, elas podem ser feitas, dividindo a alteração em pequenas etapas de preservação de comportamento;
-
Usamos a metáfora de bad smell para indicar um código que precisa de refatoração, que incluem duplicação e condicionais complexas;
-
A refatoração pode desempenhar um papel importante nas revisões de código, desde que seja feita rapidamente.
A segunda edição do livro Refactoring, de Martin Fowler, explora como podemos melhorar o design e a qualidade de nosso código com pequenos passos, sem alterar o comportamento externo. Consiste em cerca de setenta descrições detalhadas de refatorações, incluindo uma motivação para fazê-las, a mecânica e um exemplo.
Os leitores da InfoQ podem baixar um capítulo de amostra do Refactoring pela Thoughtworks.
O InfoQ entrevistou Fowler sobre as principais mudanças na 2ª edição do Refactoring, como reconhecer os problemas e como refatorar o código, como as revisões e refatoração se apoiam mutuamente, o que os líderes de tecnologia podem fazer para incentivar a refatoração, os benefícios que a refatoração traz, e as ferramentas para refatorar e para o mob programming.
O InfoQ entrevistou Kent Beck, co-autor do capítulo Bad Smells in Code, sobre como lidar com problemas dentro do código.
InfoQ: O que fez você criar a segunda edição?
Martin Fowler: O primeiro foi escrito há muito tempo e os exemplos de código são quase uma pintura rupestre (estão usando o java.util.Vector). Estava preocupado que o código estivesse muito velho fazendo com que o livro ficasse cada vez mais irrelevante para as pessoas, embora as técnicas continuem sendo úteis tanto antes quanto nos dias de hoje. Em segundo lugar, o novo livro me permitiu revisitar o tópico em um ambiente orientado a objetos menos restrito. O Java não tem funções top-level, tornando-o impossível de mostrar este tipo de refatoração.
InfoQ: Para quem este livro é destinado?
Fowler: Principalmente para desenvolvedores juniores, já que, uma vez que tenham a programação básica, estão passando a querer programar bem.
Mas há um público secundário importante: Desenvolvedores seniores, que não precisam do livro para aprender nada sobre refatoração, mas que poderão achá-lo útil para ajudar a ensinar aos outros sobre refatoração.
InfoQ: Quais são as principais mudanças nesta nova edição?
Fowler: De maneira geral, o livro não mudou muito na sua essência. A estrutura do capítulo ainda está lá e a técnica de refatoração do núcleo ainda é a mesma de vinte anos atrás. No entanto, revi e reescrevi tudo de novo. Mudei os exemplos de código, do Java para o JavaScript (EcmaScript 2005). Descartei e inclui algumas refatorações e generalizei algumas outras. Podemos encontrar um resumo das alterações neste link.
Uma mudança notável foi usar JavaScript, pois me ajudou a falar sobre refatorações só que menos voltada a orientação a objetos. Assim, posso incluir refatorações como combinar funções em classe.
InfoQ: Existem refatorações que podem ser bastante desafiadoras de se colocar em prática? Como os desenvolvedores podem tomar precauções quando as executarem?
Fowler: Não vejo refatorações específicas como mais desafiadoras do que outras. Algumas são mais prolixas, com mais etapas mecânicas, ou com mais páginas para serem lidas no livro. Mas mesmo essas refatorações mais longas não são tão difíceis. Cada passo é bastante simples, porém obtemos variações na dificuldade com a mesma refatoração mas em contexto e o escopo diferentes.
Por exemplo, vamos pegar a declaração de mudança de função. Esta refatoração deve ser usada quando quisermos alterar o nome de uma função ou adicionar/remover argumentos (essas refatorações estavam separadas na primeira edição, mas as combinei, já que as etapas para executá-las são as mesmas). No contexto mais simples, temos uma função que tem apenas uma chamada que está próxima da função no código. Nesse caso, apenas altero a chamada, testo e commito, mesmo se estivermos mudando o nome e alterando três parâmetros. Mas a mesma refatoração da declaração de mudança de função fica muito mais complicada se tivermos cem chamadas, espalhadas por toda uma base de código. Então, tenho que alterar tudo com muito mais cuidado: Copio o corpo da função antiga para a nova função, fazendo com que a função antiga funcione chamando a nova, então, uma vou substituindo as chamadas da função antiga para a nova, uma de cada vez. É um processo bem trabalhoso, mas me permite fazer pequenas alterações, mantendo o código funcionando a todo momento, que é a essência da refatoração bem-sucedida.
Com a Declaração da Mudança de Função, esta diferença de contexto era tão marcada que tenho dois conjuntos de mecânicas para ela, o que geralmente tentei evitar. Esse desafio aumenta ainda mais se for uma API publicada, já que não posso alterá-la sem falar com os meus clientes que utilizam o código. Neste caso, a função antiga que apenas faz uma chamada para a nova, pode permanecer por um longo tempo.
A principal lição, no entanto, é que as refatorações podem demorar um pouco, mas devemos sempre dividi-las em pequenos passos para manter o código funcionando. Se pudermos fazer isso, a refatoração pode ser demorada, mas não desafiadora. Se estamos nos sentindo desafiados quando fazemos uma refatoração, é um sinal de que não a dividimos em pequenos passos. Se cairmos em um buraco durante a refatoração, é um sinal de que deveríamos reverter para o último commit que está funcionando e começar de novo com etapas menores.
InfoQ: Quais são os code smells mais comuns? Como podemos lidar com eles?
Fowler: Para mim, um dos maiores problemas é a duplicação. Identificar código duplicado e descobrir como removê-lo geralmente leva a um melhor design. Como todas as coisas do mundo, isso pode ser exagerado, mas também, como a maioria das coisas, normalmente não é feito o suficiente.
Kent Beck: Como Martin já escolheu a duplicação, escolho a lógica condicional complexa. Quando vejo uma instrução
if
dentro de um loopfor
dentro de uma instruçãoif
, suspeito de imediato que há um caso de complexidade que não foi considerada. Um code smell um pouco mais abstrato que procuro são as violações do método composto, que afirma que todas as operações em uma função devem estar no mesmo nível de abstração. Por exemplo, se vejo um monte de operações de bit twiddling na mesma função com chamadas para outras funções, tenho certeza de que existe uma maneira melhor de expressar a operação.
InfoQ: Com a refatoração, a base de código geralmente fica menor à medida que o código desnecessário é removido. E se ficar maior, isso é um code smell?
Fowler: Não. Às vezes, adicionar estruturas aumenta a quantidade de linhas de código. Na verdade, isso acontece no exemplo de introdução do livro. À medida que os sistemas aumentam, a refatoração geralmente reduz o código, certamente porque retiramos a duplicação.
InfoQ: Como as revisões de código e a refatoração são compatíveis?
Fowler: A revisão é um componente importante de qualquer esforço intelectual. Quando estou escrevendo minha prosa técnica, acho essencial ter revisões sobre o meu trabalho antes da publicação. Elas identificarão maneiras pelas quais as pessoas podem interpretar mal o que escrevi e lugares onde minhas explicações não estão claras. Elas não sustentam suposições improdutivas que meu pensamento possui, que às vezes nem as noto.
Codar tem muita coisa em comum com a escrita em prosa. Nós pensamos no código como sendo instruções para o computador, mas isso perde o verdadeiro objetivo de qualquer linguagem de alto nível maior do que o código de máquina. Um bom código tem a ver com a comunicação, com quem precisa usar ou modificá-lo mais tarde, seja nós ou um terceiro. Uma parte vital da revisão de código é ser um teste de compreensibilidade, uma sensação imediata de que o código está claro ou não para o futuro programador. A revisão do código pode determinar a refatoração, fornecendo feedback necessário para dizer se a refatoração está realmente tornando o código mais claro, ou não.
A refatoração também pode ser usada como um mecanismo de revisão. Se algum código em análise não estiver claro, às vezes é importante para o revisor se reunir com a pessoa que escreveu o código e refatorá-lo junto. Isso é valioso principalmente em uma situação de mentoria onde o revisor é um programador sênior que deseja aprimorar as habilidades do júnior ou onde o revisor está mais familiarizado com a base de código e está procurando formar um novo membro de uma equipe baseado nas convenções de programação utilizando a base de código.
Para que a revisão funcione bem, é necessário que isso aconteça rapidamente, porque qualquer feedback é como leite em um dia quente. Então, precisamos de uma equipe que seja disciplinada para fazer revisões no código de maneira rápida ou programar em pares, que é um mecanismo para revisão contínua do código. Isso é verdade para todas as alterações, refatorações ou adições de recursos, mas a refatoração tem uma maior necessidade de baixa latência de revisão.
InfoQ: O que os líderes de tecnologia podem fazer para incentivar a refatoração?
Fowler: Observar o código, ver onde a refatoração pode ser útil e associar-se a pessoas para fazer a refatoração seja um bom caminho. É importante deixar claro que o código não é "feito" simplesmente para funcionar, mas também para comunicar claramente o que estamos fazendo, para que possa ser facilmente modificado no futuro.
InfoQ: Quais benefícios a refatoração traz? Como podemos convencer nossos gerentes?
Fowler: Aqui está uma armadilha perigosa. Os desenvolvedores muitas vezes justificam a alta qualidade do código como uma questão de profissionalismo, essencialmente uma justificativa moral. Mas o que os gerentes e os clientes se preocupam são os recursos que um software tem para os usuários. Quando ouvem discussões sobre qualidade, concluem que os recursos irão custar e demorar mais para serem construídos. Mas a qualidade interna do software não segue as relações usuais entre o custo e a qualidade.
Quando falo com desenvolvedores, a maioria comenta sobre sistemas de softwares que quando são adicionados novos recursos, ficam mais lentos e mais caros com o tempo, pois uma simples alteração pode levar semanas porque é difícil entender como modificar a base de código sem facilitar a criação de bugs. Mas os sistemas de software não precisam ser assim. Não só podemos reduzir essa lentidão à medida que um sistema cresce, como também podemos reverter isso. Em seguida, adicionar um recurso se torna mais rápido porque podemos criá-lo compondo recursos existentes rapidamente. A refatoração é valiosa porque nos permite manter o software em um estado saudável, evitando o acúmulo da dívida técnica.
O ponto chave aqui é que a justificativa para a refatoração, ou qualquer prática que melhore a qualidade interna do software, é um argumento *econômico*. Mantemos uma base de código limpa porque nos permite adicionar novos recursos por um custo menor e, o mais importante, adicionar novos recursos de maneira mais rápida. Como desenvolvedores, devemos sempre apresentar o argumento econômico como sendo o centro da questão, qualquer argumento baseado no profissionalismo soará como se estivéssemos em oposição a parte financeira, e o dinheiro sempre ganha da moralidade.
Infelizmente, não há dados concretos que possamos encontrar para provar o benefício econômico da qualidade interna do código, porque não podemos medir a produtividade do desenvolvimento de software. Mas do mesmo jeito não há um estudo adequado comprovando a eficácia dos paraquedas. Baseio minhas conclusões sobre a qualidade do software com base em conversas com desenvolvedores experientes. Não é uma técnica de pesquisa ideal, mas a considero muito forte, e certamente o melhor que temos atualmente.
InfoQ: Qual a sua opinião sobre ferramentas que podem nos ajudar a automatizar a refatoração?
Fowler: Se tivemos alguma, são extremamente úteis. É uma das principais razões pelas quais gosto do IntelliJ no meu programa Emacs para o Java, o suporte à refatoração é muito útil. Mas não deixemos que a falta de ferramentas nos impeça de refatorar. A maior parte da minha programação está em Ruby, onde há poucas ferramentas de refatoração para essa linguagem, mas isso não me impede de fazer isso.
InfoQ: Qual sua opinião sobre o mob programming?
Fowler: Não tenho uma opinião forte sobre isso. É algo que as equipes devem considerar e verificar se funciona para elas.
InfoQ: Se os leitores do InfoQ quiserem aprender mais sobre a refatoração, onde podem encontrar mais informação?
Fowler: Tenho um site com informações sobre a refatoração no refactoring.com. O livro é, logicamente, uma fonte que eu também sugeriria. Podemos ver as mudanças para a 2ª Edição do Refactoring para termos mais detalhes de como podemos obtê-lo.
Sobre o autor do livro
Sou autor, palestrante... Essencialmente um especialista em falar alto sobre o tema do desenvolvimento de software. Trabalho na ThoughtWorks, uma empresa de entrega de software, onde tenho o título extremamente inadequado de "cientista chefe". Escrevi meia dúzia de livros sobre desenvolvimento de software, incluindo Refactoring e Patterns of Enterprise Application Architecture. Escrevo regularmente sobre desenvolvimento de software no martinfowler.com.