“Não sou o melhor programador, mas sim um bom programador usando as melhores práticas”. – Martim Fowler
Neste post vou falar sobre duas técnicas que se bem empregadas juntas, evitam que nosso projeto de classes caia em degradação.
A refatoração é uma técnica que se propõe a melhorar o design existente de nosso código. Aplicando uma séries de pequenas mudanças e preservando o comportamento antigo. O efeito acumulativo das refatorações é bastante significativo, pois nos ajuda a alcançar dois quesitos importantes: legibilidade e manutenibilidade do código, tornando-o mais fácil de entender e simples de modificar.
Para conseguirmos refatorar com segurança, é importante que tenhamos uma base de testes sólidas, usando ferramentas que nos auxiliem como JUnit e uma outra boa prática da qual vamos falar chamada TDD (Test Drive Development). Sendo o TDD uma técnica baseada em desenvolvimento orientado a testes, além de nos prover a garantia de que o que escrevemos já nasce sendo testado, ganhamos também no aumento de coesão dos nossos componentes, pois os testes influenciam em nosso design a ponto de que para alcançarmos componentes mais fáceis de serem testados, precisam ter apenas uma responsabilidade. Assim nos inclinamos a seguir o princípio da responsabilidade única.
Enquanto estudava pra certificação Java, pelo livro da Kathy Sierra e Bert Bates, havia uma citação que dizia: “Codifique sempre como se o cara que for dar manutenção seja um psicopata violento que sabe onde você mora”. Claro que a probabilidade de você mesmo ter de dar manutenção no seu código é muito maior do que essa história do psicopata – o que dependendo do caso, pode ser muito pior.
Aqui é a onde quero chegar com tudo isso. A refatoração é frequentemente empregada no contexto TDD, onde temos o seguinte workflow:
Por que o TDD emprega em fazer o teste funcionar e só então limpar o código? Para explicar isso Martin Fowler descreve em seu livro Refactoring a metafora “Two Hats“.
1º Chapéu – Refactoring
Ao refatorar, devemos preservar o comportamento anteriormente a mudança. Refatore somente o código no qual os testes estão verdes e quando algum ficar vermelho, significa que cometemos um erro. Por este motivo, devemos fazer micro refatorações, caso algum teste falhe saberemos onde encontrar o bug.
2º Chapéu – Adicionando funções
Qualquer alteração ao código é nova funcionalidade. É adicionar novos testes e quebrar os existente, assim não estamos confinados a manter o comportamento anterior. Porém, é aconselhável fazer micro mudanças e retornar ao teste verde o mais rápido possível.
Durante a programação você pode troca-los frequentemente, mas tenha em mente que você só pode vestir um chapéu por vez.
Fazendo os testes funcionar, focamos apenas no problema que é adicionar novas funcionalidades, sem nos preocuparmos em como poderíamos conseguir o melhor design.
Uma vez que esteja funcionando, podemos nos concentrar em como melhorar o design do nosso código, enquanto fazemos micro mudanças em uma base de testes verdes.
A técnica apresentada acima é uma das maneiras de se empregar Refactoring e TDD no mesmo workflow, para lhe dar a chance de enxergar a outro lado da moeda, deixo aqui uma referencia ao blog do Martin Fowler, onde ele e mais duas grandes influências de desenvolvimento David Heinemeier e Kent Beck discutem o trade-off dessa abordagem.