Professional Documents
Culture Documents
Refatoração
Refatoração
\n";
while (locag3es.hasMoreBlements()) (
Locagao cada = (Locacao) locagdes.nextBlement () ;
/Jnostrar valores para cada locagéo
resultado += cada.lerFilme().lerTitulo() +": "+
string.valueof(cada.lerPrego()) + " \n";
resultado += "Nesta locagdo vocé ganhou " +
String -valueOf (lerTotalPontosLocadorFregiiente()) +
" pontos de locador freqiente ";
return resultado;
d
Apésextrair os célculos, posso agora criar 0 método contalHim! e reutilizar todo 0 c6-
digo de célculo que estava no método original do método conta. Nao copiei e colei, de
modo que seas regras de célculo mudarem s6 tenho um local no cédigo aonde ir. Qual-
quer outro tipo de conta seré realmente rapido e facil de preparar. A refatoracao nao de-
morou muito. Gastei a maior parte do tempo descobrindo 0 que 0 cédigo fazia e eu te-
ria que fazer isso de qualquer maneira.
Algum cédigo é copiado da versto ASCII, devido principalmente ao estabelecimen-
to do lago. Alguma refatoragao adicional poderia limpar isso. Extrair métodos para ca-
becalho, rodapé e linhas de detalhe é um caminho que eu poderia tomar. Vocé pode ver
como fazer isto no exemplo de Criar um Método Padrito (293). Mas agora os usuarios es-
tao clamando de novo. Eles estao se aprontando para alterar a classificacao dos filmes
na loja. Ainda nao esté claro que mudanas eles querem fazer, mas parece que novas
classificagGes serao introduzidas, e as existentes poderiam ser alteradas. As designacdes.
dos custos e pontos de locadores freqiientes dessas classificagdes ainda estao por ser de-
terminadas. No momento, fazer esse tipo de alteragao é pouco pratico. Tenho que entrar
nos métodos de custos e pontos de locadores freqiientes e alterar 0 cédigo condicional
para fazer as alteraces nas classificacdes dos filmes. De volta ao chapéu de refatoragao.
Substituindo a Légica Condicional no Cédigo do Prego com
Polimorfismo
A primeira parte deste problema é aquele comando switch. £ uma ma idéia fazer um
switch baseado em um atributo de outro objeto. Se vocé tiver que usar um comando
switch, ele deve ser usado sobre seus préprios dados, nao nos de outros.EEATORAGAO.
class Locagao.
double lerPrego() {
double resultado = 0;
switch (lerFilme() .lercédigoPreco()) {
case Filme NORMAL:
2;
if (lerDiasalugados() > 2)
resultado += (lerDiasAlugados() - 2) * 1.5
break;
case Filme. LANGAMENTO:
resultado += lerDiasAlugados() * 3;
break;
case Filme. INEANTIL:
resultado
resultado += 1.5;
if (erDiasAlugados() > 3)
resultado += (lerDiasAlugados() - 3) * 1.5,
break;
}
return resultado;
}
Isto significa que ler Prego deve ser movido para a classe Filme:
class Filme.
double lerPrego(int diasAlugados) {
double resultado = 0;
switch (lexCédigoPrego()) {
case Filme NORMAL:
resultado += 2;
if (diasAlugados > 2)
resultado += (diasAlugados - 2) * 1.5;
breal
case Filme. LANGAMENTO:
resultado += diasAlugados * 3;
break;
case Filme. INFANTIL:
resultado += 1.5;
if (diasAlugados > 3)
resultado += (diasAlugados - 3) * 1.5;
break;
}
return reaultado;
d
Para que isso funcione, tive que passar a duracao da locagao, 0 que, é claro, é um
dado da classe Locacao. O método efetivamente usa dois dados: a duragao da loca-
0 e 0 tipo do filme. Por que eu prefiro passar a duragao da locacao para a classe Fil-
me em vez do tipo do filme para a classe Locagao? Porque as alteragdes propostas si0
todas relacionadas a adi¢ao de novos tipos. Informagoes sobre tipos geralmente ten-
dem a ser mais volateis. Se eu alterar o tipo do filme, nao quero com isso afetar as ou-
tras classes, entao prefiro calcular 0 custo dentro da classe Filme.ReraTonagao, um Paimeino Exenrio 43
Compilei o método na classe Filme e entao alterei LerPrego na classe Locacao
para usar 0 novo método (Figuras 1.12 e 1.13):
= Cente
diasAlugados: int a am
leet) eons)
InPontosocadrragiens) leat)
lent oadeqere
i
Filme
g9Prepe:nt
Figura 1.12 Diagrama de classes antes de mover os métodos para a classe Filme
7 Cente
*
AlasAtugados nt an
lePreco) contain)
lePontost ocadereqbete) lePregootal)
leoaPontoaocaderreqdente)
1
Fine
igoP rego:
lerPrego (as:
lerPoiosocador regent (as:
Figura 1.13 Diagrama de classes apés a mover os métodos para a classe Filme.
class Locagao.
double lerPrego() {
return _filme,lerPreco(_diasAlugados) ;
}
Assim que tiver movido o método lerPreco, farei o mesmo com 0 célculo de pon-
tos de locadores freqiientes. Isto mantém ambos os métodos que variam com 0 tipo
de fita, junto a classe que possui o tip.
class Locagao ..
int lerPontosLocadorFregiente () {44 Reraronacho
if ((lerFilme ().lerCédigoPrego () == Filme.LANGAMENTO) &&
LerDiasAlugados () > 1)
return 2;
else
return 1;
}
class Locagao.
int lerPontosLocadorFreqiiente() {
return _filme. lerPontosLocadorFreqiente(_diasAlugados) ;
}
class Filme
int lerPontosLocadorFregiiente(int diasAlugados) {
if ((lercédigoPrego() == Filme.LANCAMENTO) && diasAlugados > 1)
return 2;
else
return 1;
}
E finalmente... Heranga
Temos diversos tipos de filmes que tém diferentes maneiras de responder & mesma
solicitagao. Isso parece um trabalho para subclasses. Podemos ter trés subclasses de
Filme, cada uma das quais podendo ter sua prdpria versao de custos (Figura 1.14).
Filme
lerPrego
Filme Normal Filme infant Flime Langamento
Praga lerPrego lerProgo
Figura 1.14 Usando heranga na classe Filme.
Isto me permite substituir o comando switch usando polimorfismo. Infelizmente,
isso apresenta uma pequena falha ~ nao funciona. Um filme pode mudar sua classi-
ficago durante sua existéncia. Um objeto nao pode alterar sua classe durante sua
existéncia. Todavia, hé uma solugao: o padrao State [Gangue dos Quatro]. Com o pa-
drao State as classes se parecem coma figura 1.15.ReraTonagao, um Paimeino Exeurio 45
Filme Prego
vere 9 1 | ere
‘etumpreglerPrego
Prego Normal Prego Langamento
lePrego lerPrego lerPrago
Figura 1.18 Usando o padrao State em uma classe Filme.
Acrescentando a referéncia a classe Preco, podemos criar as subclasses a partir
dessa e alterar 0 preco sempre que precisarmos.
Se vocé estiver familiarizado com os padrdes da Gangue dos Quatro, pode fi-
car imaginando, “Isto é um State ou uma Strategy?” A classe Prego representa um
algoritmo para o calculo do preco (caso em que eu prefiro chamé-la formadorPre-
0 ou estratégiaPreco) ou um estado do filme (Star Trek X é um langamento). Nesse
estagio, a escolha do padrao (e do seu nome) reflete como vocé quer pensar a res-
peito da estrutura. No momento, estou pensando nela como o estado de um filme.
Se mais tarde decidir que o padrao Strategy comunica melhor minha intencao, irei
refatorar mudando os nomes.
Para introduzir o padrao State, usarei trés refatoracdes. Primeiro, moverei o com-
portamento de enumeracao para o padrao State com Substituir Enumeragao pelo Pa-
drao State/Strategy (195). A seguir, posso usar Mover Método (125) para mover 0 co-
mando switch para a classe prego. Finalmente, usarei Substituir Condigdo por Polimor-
‘fismo (218) para eliminar 0 comando switch,
Comego com Substituir Enumeragio pelo Padrao State/Strategy (195). O primeiro
passo é usar Auto-Encapsular Campo (150) na enumeragao para garantir que todas as
referéncias a ela passem por métodos de leitura e de gravacao (métodos get e set). De-
vido ao fato da maior parte do cédigo vir de outras classes, a maioria dos métodos ja
usa os métodos ler. Entretanto, os construtores acessam 0 cédigo do prego:
class Filme.
public Filme(String titulo, int codigoPreco) {
titulo = titulo;
LcodigoPrego = codigoPreso;
}
Posso usar 0 método gravar em vez disso:
class Filme
public Filme(String titulo, int codigoPreco) {
titulo = titulo;
gravarCédi goPrego(codigoPrego) ;46 __Reraronacho
‘Compilo e testo para me assegurar de que nao estraguei nada. Agora adiciono as
novas classes. Fornego 0 comportamento enumerado no objeto prego. Fago isso com
um método abstrato na classe do prego e métodos concretos nas subclasses:
abstract clase Prego {
abstract int lercédigoPreco() ;
}
class PregoInfantil extends Prego {
int lerCédigoPrego() {
return Filme. INFANTIL;
)
}
class Pregobangamento extends Prego (
int lercédigoPreco() {
return Filme. LANCAMENTO;
}
}
class PregoNormal extends Prego {
int lercédigoPrego() {
return Filme.NORMAL;
)
}
Neste momento, posso compilar as novas classes.
Agora preciso alterar os métodos de acesso ao cédigo do preco da classe Filme
para que usem a nova classe:
public int lerCédigoPrego () {
return _codigoPrego;
}
public void gravarC6digoPrego (int arg) {
_codigoPreco = arg;
d
private int _codigoPrego;
Isto significa substituir 0 campo de c6digo do prego por um campo de prego e al-
terar os métodos de acesso:
clase Plime.
public int lercodigopreco() (
return _prege.lercedigoPrego() ;
)
public void gravarcedigoPrego(int ara) {
switch (arg) {
case NORMAL:
“prego = new Pregotlormal ();
break;
case INPANTIL:
_prego = new PregoInfantil();
break;ReraTonagao, um Paimeino Exeuo 47
case LANCAMENTO:
_prego = new PregoLangamento();
break;
default:
throw new IllegalArgumentException("Cédigo de Prego Incorreto");
d
private Prego prego;
Posso agora compilar e testar, e 0s métodos mais complexos nao percebem que 0
mundo mudou.
Agora aplico 0 Mover Método (125) em lerPrego:
class Filme
double lerPrego(int diasAlugados) {
double resultado = 0;
switch (lerCédigoPrego()) {
case Filme.NORMAL:
resultado
if (diasAlugados > 2)
resultado += (diasAlugados - 2) * 1.5;
break;
case Filme. LANGAMENTO:
resultado += diasAlugados ¥ 3;
break;
case Filme. INFANTIL:
resultado += 1.5;
if (diasAlugados > 3)
resultado += (diasAlugados - 3) * 1.5;
break;
}
return resultado;
)
E simples mover:
clase Filme.
double lerPrecolint diasAlugados) — {
return _preco.lerPreco (diasAlugados) ;
d
clase Prego.
double lerPrego(int diasAlugados)
double resultado = 0;
switch (lercédigoPreco()) {
‘case Filme.NORMAL:
resultado
if (diaoAlugados > 2)
resultado += (diasAlugados - 2) * 1.48 __Reraronacho
break;
case Filme. LANCAMENTO:
resultado += diasAlugados * 3;
break;
case Filme. INFANTIL:
resultado += 1.5;
if (diasAlugados > 3)
resultado += (diasAlugados - 3) * 1.5;
break;
}
return reaultado;
d
Assim que esteja movido, posso comegar a usar Substituir Comando Condicional
por Polimorfismo (218):
class Prego
double lerPrego(int diasAlugados) {
double resultado = 0;
switch (lerCédigoPrego()) {
case Filme.NORMAL:
resultado
if (diasAlugados > 2)
resultado += (diasAlugados - 2) * 1.5;
break;
case Filme. LANCAMENTO
resultado += diasAlugados ¥ 3;
break;
case Filme. INFANTIL:
reaultado += 1.5
if (diasAlugados > 3)
resultado += (diasAlugados - 3) * 1.5;
break;
}
return resultado;
}
Faco isso tomando uma das alternativas do comando case por vez e criando no
seu lugar um método sobrescrito (override). Comeco com PregoNormal:
class PregoNormal
double lerPrego (int diasAlugados) {
double resultado = 2;
if (iasalugados > 2)
resultado += (diasAlugados - 2) * 1.5;
return resultado;
}
Isso anula o case correspondente na superclasse, a qual deixo como est. Compi-
lo e testo essa alteracao e entao vou para o proximo case. Compilo e testo novamen-
te. (Para assegurar que estou executando 0 codigo da subclasse, gosto de deliberada-
mente colocar uma falha e executé-lo para garantir que o teste falhe. Nao que eu se-
ja paranéico ou algo parecido).ReraTonagao, um Primeino Exeuo 49
class PregoInfantil
double lerPrego (int diasAlugados) {
double resultado = 1.5;
if (diasAlugados > 3)
(diasAlugados - 3) * 1.5;
return resultado;
resultado
clase Pregotancamento .
double lerPreco (int diasAlugados) {
return diasAlugados * 3;
d
Quando tiver terminado todos os pasos, declaro 0 método Preco.lerPreco como
abstrato:
class Prego
abstract double lerPrego (int diasAlugados) ;
Agora posso executar 0 mesmo procedimento com lerPontosLocadorFre-
qtiente:
class Filme
int lerPontosLocadorFreqiente(int diasAlugados) (
if ((lercédigoPreco() == Filme.LANGAMENTO) && diasAlugados > 1)
return 2;
else
return 1;
)
Primeiro, movo 0 método para a classe Prego:
Clase Filme .
int lerPontostocadorFregiiente (int diasAlugados) (
return _prego. lerPontosLocadorfreqiente (diasAlugados) ;
}
Clase Prego .
int lerPontostocadorFregiente (int diasAlugados) (
if ({ lerc6digoPrego () == Filme.LANGAMENTO) && (diasAlugados > 1)
return 2;
else
return 1;
}
Neste caso, entretanto, nao torno o método da superclasse abstrato. Em vez dis-
so, crio um método de sobrescrita somente para os langamentos e deixo um método
definido (como default) na superclasse:
Class PregoLangamento
int lerPontosLocadorFreqiente (int diasAlugados) {
return (diasAlugados > 1)? 2:1;50
RleraTonagho
Class Prego
int lerPontosLocadorFreqiente (int diasAlugados) {
return 1;
}
Aplicar o padrao State foi um esforgo e tanto. Valeu a pena? O ganho é que, se eu
alterar qualquer comportamento do preco, acrescentar novos precos ou acrescentar
comportamento adicional dependente do prego, essa mudanga ser4 muito mais facil
de ser feita. O resto da aplicacao nao fica sabendo a respeito do uso do padrao State.
Para a pequena quantidade de comportamento, fungao do prego, que tenho no mo-
mento, isso nao é grande coisa. Em um sistema mais complexo, com uma diizia ou
mais de métodos dependentes do prego, isso faria uma grande diferenga. Todas es-
sas alteracdes foram pequenos passos. Parece lento escrever dessa forma, mas nao ti-
ve que abrir o depurador nenhuma vez, de modo que o proceso realmente fluiu ra-
pidamente. Levou muito mais tempo para eu escrever esta secao do livro do que pa~
ra alterar 0 cédigo.
Completei agora a segunda refatoragao importante. Vai ser muito mais fécil alte-
rar a estrutura de classificagao de filmes e mudar as regras de cobranga e o sistema
de pontuagao de locadores freqiientes. As Figuras 1.16 e 1.17 mostram como 0 pa-
drao State trabalha com a informagao de preco.
vumiente umaloccagio unFilme umPrego
; 1 T
cova ; \ '
‘erro
1 nt ; \ \
para tads soaps Prego ! !
\ \
lePrepo(das)
lerego(dias)
1
a I
Ipara todas as lcagées]lorPontosLocadoFrequente
> reece
———7 lerPonos.ocadorFreqiente(is)
Figura 1.16 InteragSes usando o padrio State.Reraronagao, uM Primeino ExemeLo 51
Filme
tuo: sting 1
lerPrego(as: int)
lerrego(is: int)
Ip cobsleneteteneltertt lerPortosLocadorFrequenteiasint
1 Cd
Pregolnantit PregoNormal
lesPregoasint) lePregoiiasint)
PregoLangamento
lePregoias: int
leona ocadorFrequento(as: ty
= ‘lente
asus * rome: Seng
lero) cental)
lePonoa. ocadrFeqiert) certain ()
lePrgoTota()
lerotaPontoa ccadorreqiene()
Figura 1.17 Diagrama de classes apés a adigéo do padido State
Consideracées Finais
Este é um exemplo simples, mas espero que Ihe dé uma idéia do que é refatoragao.
Usei diversas refatoragdes, incluindo Extrair Método (100), Mover Método (125) e Subs-
tituir Comando Condicional por Polimorfismo (218). Todas essas levam a responsabilida-
des melhor distribuidas e c6digo em que é mais facil realizar manutencdes. Realmen-
te parece diferente do estilo de cédigo procedural, e demora um pouco para se acos-
tumar, porém, uma vez que vocé tenha se acostumado a ele, é dificil voltar aos pro-
gramas procedurais.
Alico mais importante deste exemplo é 0 ritmo da refatoracdo: teste, pequena
alteragao, teste, pequena alteracdo, teste, pequena alteragao. E esse ritmo que permi-
te a refatoracao andar rapidamente e com seguranca.
Se vocé chegou até aqui, deve entender agora do que trata a refatoragao. Pode-
mos agora avancar para alguns conceitos basicos, principios e teoria (embora nao de-CAPITULO 2
Principios da Refatoracao
Ja refatoracao. Agora é hora de voltar e ver os principios chave da refatoragao
Ore: anterior deve ter Ihe dado uma boa idéia a respeito do que se trata
ealgumas das questdes que vocé precisa considerar ao usar refatoragao
Definindo Refatoracao
Fico sempre um pouco desconfiado de definigdes porque todos tém as suas, mas
quando vocé escreve um livro acaba escolhendo suas prdprias definigdes. Neste ca-
so, estou baseando minhas definigGes no trabalho feito pelo grupo de Ralph Johnson
e diversos associados.
Aprimeira coisa a dizer é que a palavra Refatoragio tem dois significados, depen-
dendo do contexto. Vocé pode achar isto irritante (eu certamente acho), mas serve co-
mo exemplo da realidade de trabalhar com linguagem natural.
Aprimeira definigao é a da forma substantiva
1, Refatoragao (substantivo): uma alteragao feita na estrutura interna do software para
J= tornd-lo mais facil de ser entendido e menos custoso de ser modificado sem alterar seu
comportamento observtvel.
Vocé pode encontrar exemplos de refatoragies no catélogo, tais como Extrair Mé-
todo (100) e Subir Campo na Hierarquia (274). A refatoracao propriamente dita é nor-
malmente uma pequena alteracao no software, ainda que uma refatoragao possa en-
volver outras. Por exemplo, Extrair Classe (132) normalmente envolve Mover Método
(125) e Mover Campo (129).Paincipios oa Reraroracho 53
O outro uso de refatoragio é na forma verbal.
YL Refatorar (verbo): reestruturar software aplicando uma série de refatoragdes sem alte-
rar seu comportamento obserodvel.
Vocé poderia entao gastar algumas horas refatorando, durante as quais poderia
aplicar algumas dtizias de refatoragGes individuais.
Jéme perguntaram “A refatoracao é apenas limpeza de cdigo?” De certo modo,
a resposta é sim, mas acho que refatoragao vai mais longe que isso, porque fornece
uma técnica para limpar cédigo de uma maneira mais eficiente e controlada. Desde
que comecei a usar refatoracao, percebo que limpo cédigo muito mais eficazmente
que antes. Isto acontece porque sei quais refatoracdes usar e como usé-las de um mo-
do que minimize as falhas, e eu testo a cada oportunidade possivel.
Devo explicar com mais detalhes alguns dos pontos de minhas definig6es. Pri-
meiro, o propésito da refatoracao é tornar o software mais facil de entender e mod:
car. Vocé pode fazer muitas mudangas no software que alterem pouca coisa ou nada
no comportamento observavel. Somente as mudangas feitas para tornar o software
mais facil de entender sao consideradas refatoracdes. Um bom contraste é a otimiza-
do de desempenho. Assim como a refatoracio, a otimizacao de desempenho geral-
mente nao altera 0 comportamento de um componente (além da sua velocidade), ela
altera apenas a estrutura interna. Entretanto, o propdsito é diferente. A otimizagao de
desempenho muitas vezes torna o cédigo mais dificil de entender, mas vocé precisa
fazé-la para obter o desempenho de que necesita.
A segunda coisa que quero destacar é que a refatoragao nao altera 0 comporta-
mento observavel do software. Esse ainda executa a mesma fungao de antes. Qual-
quer usuario, seja ele um usuério final ou outro programador, nao é capaz de dizer
que algo mudou.
Os Dois Chapéus
Esse segundo ponto leva metfora de Kent Beck dos dois chapéus. Quando usa re-
fatoragao para desenvolver software, vocé divide seu tempo entre duas atividades dis-
tintas: adicionar funcionalidades e refatorar. Quando adiciona funcionalidades, vocé
nao deve alterar cédigo preexistente. Vocé est apenas adicionando novas capacida-
des. Vocé pode medir seu progresso adicionando testes e os executando. Quando vo-
cé refatora, faz questo de nao acrescentar novas funcionalidades; apenas reestrutura
© cédigo. Vocé nao acrescenta novos testes (a ndo ser que encontre um caso que no
havia percebido antes); vocé apenas muda os testes quando isso for absolutamente
necessirio para lidar com uma alteragao em uma interface.
A medida que vocé desenvolve software, provavelmente se descobre trocando
chapéus com freqiiéncia. Vocé comeca tentando adicionar uma nova fungao e perce-
be que seria muito mais facil se o cédigo estivesse estruturado de forma diferente.
Entao vocé troca de chapéu e refatora durante um certo perfodo. Assim que 0 cédigo
estiver mais bem estruturado, vocé troca de chapéu e acrescenta a nova fungao. As-
sim que vocé tenha a nova funcao ativa, percebe que a codificou de uma maneira di-
ficil de entender e entao troca de chapéu novamente e refatora. Tudo isso pode levar
apenas dez minutos, mas durante este tempo vocé deve estar ciente de qual chapéu
esté usando.54
RlerAToRagho
Por Que Vocé Deve Refatorar?
Nao quero apregoar a refatoracao como a cura de todos os problemas do software. Ela
nao é uma panacéia para todos os problemas. Ainda assim, é uma ferramenta valio-
sa, um alicate de prata que Ihe ajuda a manter seu c6digo seguro. Refatoragao é uma
ferramenta que pode, e deve, ser usada para diversos propésitos.
Refatorar Melhora o Projeto do Software
Sem refatoragdo, o projeto do programa termina por se deteriorar. A medida que as
pessoas alteram o cédigo ~ alteracdes para executar objetivos de curto prazo ou en-
tao alteragdes feitas sem uma compreensio total do projeto do cédigo — 0 cédigo se
desestrutura. Torna-se mais dificil visualizar 0 projeto ao ler 0 cédigo. Refatoracao é
como arrumar o cédigo. As partes do cédigo que nao estejam no lugar apropriado
so removidas. A perda de estrutura do cédigo tem um efeito cumulativo. Quanto
mais dificil & visualizar o projeto a partir do cédigo, mais dificil sera preserva-lo e
mais rapidamente ele se desestruturara. A refatoracao sistematica ajuda 0 cédigo a
conservar sua forma.
Um sistema mal projetado normalmente precisa de mais cédigo para fazer as
mesmas coisas, muitas vezes porque o mesmo cédigo é replicado em diversos lugares
diferentes. Assim, um aspecto importante na melhoria do projeto é a eliminacao de
cédigo duplicado. A importancia disto recai sobre futuras modificacdes no cédigo. Re-
duzir a quantidade de cédigo nao faré o sistema rodar mais rapidamente, porque 0
efeito no desempenho dos programas raramente é significativo. Reduzir a quantida-
de de cédigo faz, todavia, uma grande diferenca sobre a manutencao desse cédigo.
Quanto mais cédigo houver, mais dificil seré modificé-lo corretamente. Ha mais cédi-
go para ser entendido. Vocé altera um trecho de cédigo aqui, e o sistema nao faz 0 es-
perado porque vocé nao alterou o cédigo em outro lugar que faz a mesma coisa em
um contexto levemente diferente. Eliminando as c6pias, vocé se assegura de que 0 c6-
digo diz tudo uma e apenas uma vez, o que é a esséncia do bom projeto.
Refatorar Torna 0 Software Mais Facil de Entender
Programar é de certa forma conversar com 0 computador. Vocé escreve cédigo que
diz a esse 0 que fazer, e ele responde fazendo exatamente o que vocé Ihe diz. Com o
passar do tempo, vocé diminui a distancia entre o que quer que o computador faga e
‘© que vocé Ihe manda fazer. Programar dessa forma é dizer ao computador exata-
mente o que vocé quer. Ha todavia outro usudrio do seu cédigo fonte. Alguém tenta-
ré ler seu cédigo dentro de alguns meses para fazer algumas alteraqdes. Esquecemos
facilmente desse usuario adicional do cédigo, embora seja na verdade o mais impor-
tante. Quem se importa se o seu computador gastar alguns ciclos a mais para compi-
lar algo? O que faz diferenca é se um programador tiver de gastar uma semana para
fazer uma alteragao que teria levado apenas uma hora se ele tivesse entendido seu
cédigo.
O problema é que, quando esta tentando fazer seu programa funcionar, vocé nao
estd pensando no futuro desenvolvedor. E necessaria uma alteracao de ritmo para fa-
zet modificagSes que tornem o cdigo mais facil de ser entendido. A refatoracao aju-
daa tornar seu cdigo mais legivel. Ao refatorar, vocé tem cédigo que funciona mas
que nao esté estruturado da forma ideal. Um pouco de tempo gasto refatorando po-Principios oa Reraroracho 55
de fazer com que o c6digo comunique melhor seu propésito. Programar dessa forma
& explicar ao computador precisamente o que vocé quer dizer.
Nao estou sendo necessariamente altrufsta a respeito deste tema. Muitas vezes,
este futuro desenvolvedor sou eu mesmo. Aqui, refatorar é particularmente impor-
tante. Sou um programador muito preguigoso. Uma de minhas formas de preguica é
que nunca me lembro de coisas sobre 0 cédigo que escrevo. De fato, tento delibera-
damente nao me lembrar de algo que eu possa procurar, porque tenho medo de que
meu cérebro fique entupido. Tento colocar tudo que devo recordar no cédigo, de mo-
do que nao tenha que me lembrar disso. Desta forma, fico menos preocupado com a
Old Peculier* [Jackson] matando meus neurénios.
Essa compreensibilidade também funciona de outra forma. Uso refatoragao para
me ajudar a entender cédigo com 0 qual nao esteja familiarizado. Quando vejo tal ti-
po de c6digo, tenho que tentar entender o que ele faz. Olho algumas linhas e digo pa-
ra mim mesmo, ah, é isso que este trecho de cédigo esta fazendo. Usando refatora-
do, no me limito ao entendimento mental. Eu realmente altero o cédigo para que
reflita melhor minha compreensdo e entao testo esta compreensdo executando nova-
mente 0 c6digo para ver se ele ainda funciona.
Desde 0 inicio, fago refatoragdes como essa em detalhes. A medida que o cédigo
vai ficando mais claro, descubro que posso ver coisas a respeito do projeto que nao
conseguia ver antes. Se eu nao tivesse alterado o eddigo, provavelmente nunca teria
visto essas coisas, porque ndo sou suficientemente esperto para visualizar tudo isso
na minha cabeca. Ralph Johnson descreve estas refatoracdes iniciais como limpar a
sujeira da janela para que vocé possa ver além. Quando estou estudando cédigo, des-
cubro que a refatoracao me leva a niveis mais altos de compreensao que de outra for-
ma eu ndo atingiria.
Refatorar Ajuda a Encontrar Falhas
Amelhora no entendimento do cédigo também me ajuda a localizar falhas. Admito
que nao sou muito bom em encontrar falhas. Algumas pessoas conseguem ler um
bloco de cédigo e achar falhas, eu nao. Entretanto, descubro que, se refatoro cédigo,
trabalho pesado na compreensao do que ele faz, e aplico esse novo conhecimento de
volta no cédigo. Clareando a estrutura do programa, clareio certas suposiges que
havia feito, até o ponto em que nem mesmo eu consigo evitar de achar as falhas.
Isso me lembra de uma frase que Kent Beck sempre diz a respeito de si préprio,
“Nao sou um grande programador; sou apenas um bom programador com étimos
habitos”. Refatorar me ajuda a ser muito mais efetivo na escrita de cédigo robusto.
Refatorar Ajuda a Programar mais Rapidamente
No final, todos os pontos anteriores levam a este: Refatorar ajuda vocé a desenvolver
cédigo mais rapidamente.
Isto nao parece intuitivo. Quando falo sobre refatoragao, as pessoas podem ver
facilmente que ela melhora a qualidade. Melhorar o projeto, melhorar a legibilidade,
reduzir as falhas, tudo isto melhora a qualidade. Mas isto tudo nao reduza velocida-
de de desenvolvimento?
* Node RT: Marea de cerveja56
RlerAToRagho
Eu realmente acredito que um bom projeto é essencial para desenvolvimento
rapido de software. De fato, a grande motivagao para se ter um bom projeto é permi-
tir o desenvolvimento rapido. Sem um bom projeto, vocé pode progredir rapidamen-
te durante um certo tempo, mas logo o projeto ruim comega a atrasar seu trabalho.
‘Vocé perde tempo procurando e consertando falhas em vez de adicionar novas fun-
cionalidades. Mudangas demoram mais 4 medida que vocé tenta compreender o sis-
tema e encontrar cédigo duplicado. Introduzir novas caracteristicas demanda mais
c6digo, quando é necessério remendar um remendo que remenda outro remendo no
cédigo original.
Um bom projeto é essencial na manutencao da velocidade de desenvolvimento
de software. Refatorar ajuda vocé a desenvolver software mais rapidamente, porque
evita que o projeto do sistema se deteriore. A refatoracdo pode até mesmo melhorar
um projeto.
Quando Vocé Deve Refatorar?
Quando falo sobre refatorac4o, muitas vezes me perguntam sobre como ela deve ser
programada. Devemos alocar duas semanas a cada dois meses para refatorar?
Na maioria dos casos, sou contra separar tempo para refatorar. Na minha visio,
a refatoracao nao é uma atividade para a qual vocé separa tempo. Refatoragao é algo
que voce faz todo o tempo em pequenas rajadas. Vocé nao decide refatorar, voce re-
fatora porque quer fazer alguma outra coisa qualquer e refatorar ajuda a fazé-lo.
A Regra de Trés
Aqui esta uma diretriz que Don Roberts me deu: na primeira vez em que faz algo,
vocé apenas faz. Na segunda vez em que faz algo parecido, vocé estremece diante da
duplicagao, mas a faz de qualquer forma. Na terceira vez em que faz algo parecido,
vocé refatora.
Trés vezes ¢ voc’ refatora.
Refatore Quando Acrescentar Fungdes
Ahora mais comum para refatorar é quando quero adicionar uma nova caracteristi-
ca.aalgum software. Muitas vezes a primeira razao para refatorar aqui é me ajudar a
compreender algum cédigo que preciso modificar. Este cédigo pode ter sido escrito
por outra pessoa ou por mim. Toda vez que tenho que pensar para entender o que o
cédigo faz, me pergunto se posso refatorar o cédigo para tornar esse entendimento
mais rpido. Entao eu o refatoro. Em parte, isso é para a préxima vez que eu passar
por aqui, mas principalmente porque posso entender mais coisas se clarear 0 cédigo
A medida que vou adiante.
O outro motivo que conduz a refatoracaio aqui é um projeto que nado me ajuda a
acrescentar uma nova funcionalidade facilmente. Olho o projeto e digo para mimPaincipios oa Reraronacho 57
mesmo “Se eu tivesse projetado o cédigo desta forma, acrescentar esta caracterfstica
seria facil”. Nesse caso, ndo lamento meus erros passados — eu os conserto refatoran-
do. Fago isso em parte para tornar melhorias futuras mais féceis, mas principalmen-
te porque descobri que é 0 meio mais rapido. Refatorar é um processo rapido e tran-
qiiilo. Uma vez que vocé tenha refatorado, adicionar uma caracteristica pode ser
muito mais rapido e traniiilo.
Refatore Quando Precisar Consertar uma Falha
No conserto de falhas, muito da utilidade da refatoracao vem do fato de tornar 0 c6-
digo mais compreensivel. Quando olho o cédigo tentando compreendé-lo, refatoro
para ajudar a melhorar minha compreensao. Muitas vezes descubro que este pro-
cesso ativo de trabalho com cédigo ajuda a encontrar a falha. Um modo de encarar
isso é que, se vocé recebe uma notificacao de falha, é um sinal de que precisa refato-
rar, porque 0 cédigo nao estava claro o suficiente para que percebesse que havia
uma falha.
Refatore Enquanto Revisa 0 Cédigo
Algumas organizacoes fazem revisdes de c6digo regulares. Aquelas que nao o fazem
ficariam melhor se fizessem. Revisdes de cdigo ajudam a difundir conhecimento
através de uma equipe de desenvolvimento. As revisdes facilitam a transmiss4o do
conhecimento dos desenvolvedores mais experimentados para os menos experien-
tes. Elas ajudam mais pessoas a entender mais aspectos de um sistema grande de
software. Elas também s4o muito importantes na escrita de cédigo claro. Meu cédigo
pode parecer claro para mim, mas nao para minha equipe. Isto é inevitavel - 6 mui-
to dificil para as pessoas se colocarem no lugar de alguém que nao esteja familiariza-
do com as coisas nas quais estao trabalhando. Revisdes também dao a oportunidade
de mais pessoas sugerirem idéias titeis. Eu precisaria de uma semana para pensar em
tantas boas idéias. Fazer outras pessoas contribuirem torna minha vida mais facil, en-
tao busco sempre por novas revises.
Descobri que refatorar me ajuda a revisar 0 cédigo de outras pessoas. Antes de
eu comesar a refatorar, podia ler o cédigo, obter algum grau de compreensao do mes-
mo e fazer algumas sugestées. Agora quando tenho uma idéia, considero se ela po-
de ser facil e imediatamente implementada com refatoragao. Em caso positivo, refa-
toro. Depois de fazer isso algumas vezes, posso ver mais claramente como 0 cédigo
se parece com as sugestdes ja implementadas. Nao tenho que imaginar como seria,
posso ver como &. Como resultado disso, posso vir com um segundo nivel de idéias
que nunca teria percebido caso nao tivesse refatorado.
Refatorar também ajuda a revisao do cédigo a gerar resultados mais concretos.
Nao s6 as sugestdes aparecem, como também muitas delas s4o imediatamente im-
plementadas. Vocé sai do exercicio com uma sensacao de realizagao muito maior.
Para fazer este processo funcionar, vocé precisa ter pequenos grupos de revisao.
Minha experiéncia sugere ter um revisor e o autor trabalhando no cédigo juntos. O
revisor sugere alteragdes e ambos decidem se elas podem ser facilmente refatoradas.
Em caso afirmativo, eles executam essas alteracdes.
Se 0 objetivo é uma revisdo de projeto, freqiientemente é melhor obter diversas
opinides em um grupo maior. Mostrar cédigo muitas vezes nao é a melhor maneira
\n";
}
/Jadicionar linhas de rodapé
resultado += "