Escolar Documentos
Profissional Documentos
Cultura Documentos
Ok, sim, é, mas há mais do que isso.A refatoração é um tipo de mudança de código,
mas tem uma grande restrição que torna “mudança de código” uma maneira impre-
cisa de descrevê-lo: você não altera o comportamento do código. Duas questões imedi-
atas devem vir à mente:
Detalhes de implementação
Comportamento não especificado e não testado
atuação
Outra abordagem, apoiada por William Opdyke, cuja tese é o trabalho fundamental
sobre refatoração, enfatiza o uso de ferramentas automatizadas que são responsáveis
por alterar o código e garantir a segurança antes de fazê-lo. Os codificadores profissio-
nais podem descobrir que a remoção do elemento humano limita os tipos de altera-
ções que podem ser feitas, pois o número de alterações que podem ser garantidas
como “seguras” está confinado à funcionalidade das ferramentas.
Escrever ferramentas para abranger todo o catálogo de refatoração proposto por Mar-
tin Fowler em seu livro seminal, Refactoring: Improving the Design of Existing Code
(Addison-Wesley), seria extremamente difícil. E em JavaScript, uma linguagem dinâ-
mica e multiparadigmática com um ecossistema repleto de variantes (veja o Capítulo
2 ), essas ferramentas estão fadadas a ficar ainda mais atrás da imaginação de um
refatorador.
AV I S O ! U S E O C O N T R O L E D E V E R S Ã O !
Qualquer forma de “alteração de código” traz um risco significativo para sua base de código se
você não puder revertê-la facilmente para uma versão anterior e segura.Se você não tem bac-
kups versionados da base de código que planeja refatorar, ponha este livro de lado e não o pe-
gue novamente até que seu código esteja sob controle de versão.
Se você ainda não estiver usando o controle de versão, provavelmente desejará usar o Git e pro-
vavelmente desejará fazer backup do seu trabalho no GitHub .
É certo que a abordagem deste livro pode parecer reativa e descuidada em compara-
ção com os caminhos anteriores da automação e da mecânica. No entanto, o processo
- o ciclo "vermelho" (estado de falha de um teste), "verde" (estado de aprovação de um
teste), "refatorar", com o objetivo de reverter rapidamente se as coisas derem errado -
empregado neste livro é com base em como as equipes focadas na qualidade operam
com ferramentas que são populares entre elas. Talvez mais tarde, a refatoração auto-
matizada alcance o extenso catálogo de refatorações de Fowler, bem como tudo o que
é apresentado neste livro, mas eu não contaria com isso em breve.
function byTwo(number){
return number * 2;
Em vez disso, poderíamos escrever uma função que atinja o mesmo objetivo de uma
maneira ligeiramente diferente:
function byTwo(number){
E qualquer um deles funcionará bem para muitas aplicações. Quaisquer testes que
usamos para a byTwo função seriam basicamente apenas um mapeamento entre um
número de entrada e um número de saída que é o dobro do valor. Mas, na maioria
das vezes, estamos mais interessados nos resultados do que se o operador * ou é
usado. << Podemos pensar nisso como um detalhe de implementação .Embora você
possa pensar em detalhes de implementação como este como comportamento , é um
comportamento que é insignificante se tudo o que nos importa é a entrada e a saída
de uma função.
Se usarmos a segunda versão de byTwo por algum motivo, podemos descobrir que ela
quebra quando nosso number argumento fica muito grande (tente com um trilhão:
1000000000000 << 1 ). Isso significa que de repente nos preocupamos com esse de-
talhe de implementação?
Não. Nós nos importamos que nossa saída esteja quebrada. Isso significa que nosso
conjunto de testes precisa incluir mais casos do que pensávamos inicialmente. E pode-
mos trocar essa implementação por uma que satisfaça todos os nossos casos de teste;
se essa é return number * 2 ou return number + number não a nossa principal
preocupação.
Mudamos os detalhes de implementação, mas dobrar nosso número é o comporta-
mento com o qual nos preocupamos. O que nos interessa também é o que testamos
(manualmente ou de forma automatizada). Testar as especificidades não é apenas
desnecessário em muitos casos, mas também resultará em uma base de código que
não podemos refatorar tão livremente.
TESTANDO O PRÓPRIO JAVASCRIPT
assert = require('assert');
A propósito, essa primeira linha produzirá uma saída assustadora se você estiver em
um console de nó.Mas não se preocupe com isso; está apenas mostrando o que carre-
gou. Além disso, o console do nó já tem assert , portanto, você pode deixar de fora a
primeira linha se não estiver trabalhando em um arquivo .js . Todos os relatórios de
segunda linha são undefined , o que pode parecer estranho. Isso é normal. Tente
afirmar algo falso como assert(3 === 2) , e você verá um erro.
Se você fizer afirmações como essas, estará testando o próprio JavaScript: seus núme-
ros, + operador e === operador. Da mesma forma, e com mais frequência, você pode
se encontrar testando bibliotecas:
_ = require('underscore');
Isso está testando para ver se a biblioteca de sublinhado se comporta conforme o es-
perado. Testar detalhes de implementação de baixo nível como esse é útil se você esti-
ver explorando uma nova biblioteca ou uma parte desconhecida do JavaScript, mas
geralmente é suficiente confiar nos testes que os próprios pacotes possuem (qualquer
boa biblioteca terá seus próprios testes). Há duas ressalvas para isso, no entanto.Pri-
meiro, os “testes de sanidade” são necessários para garantir que alguma função ou bi-
blioteca tenha sido disponibilizada para o seu ambiente, embora esses testes não pre-
cisem permanecer após a estabilização do ambiente. Em segundo lugar, se você esti-
ver escrevendo testes para se ajudar a ter confiança no código (mais sobre isso de-
pois), testar o comportamento de uma biblioteca é apropriado para demonstrar o có-
digo em ação.
Por que não nos importamos com comportamento não
especificado e não testado?
O grau em que especificamos e testamos nosso código é literalmente o esforço que de-
monstra nosso cuidado com seu comportamento.Não ter um teste, um procedimento
manual para execução ou pelo menos uma descrição de como deve funcionar signi-
fica que o código é basicamente inverificável.
Vamos supor que o código a seguir não tenha testes de suporte, documentação ou pro-
cessos de negócios descritos por meio dele:
doesOtherThings(args);
doesOtherOtherThings(args, callback);
return 5;
};
Nós nos importamos se o comportamento muda? Na verdade sim! Esta função pode
estar mantendo muitas coisas juntas. Só porque não podemos entendê-lo não o torna
menos importante. No entanto, isso o torna muito mais perigoso.
Essa situação também não se limita ao código herdado. Também é impossível refato-
rar código novo e não testado sem testes, sejam eles automatizados ou manuais.
COMO AS CONVERSAS SOBRE REFATORAÇÃO DEVEM ACONTECER ATÉ QUE OS TESTES SEJAM
ESCRITOS
"Não."
“Refatorando o–”
"Não."
“Refa–”
"Não."
No que diz respeito à refatoração, inicialmente não nos importamos com o desempe-
nho.Como com nossa função de duplicação algumas seções atrás, nos preocupamos
com nossas entradas fornecendo as saídas esperadas. Na maioria das vezes, podemos
nos apoiar nas ferramentas que nos são fornecidas e nosso primeiro palpite em uma
implementação será bom o suficiente . O mantra aqui é “escrever primeiro para os
humanos”.
Bom o suficiente para uma primeira implementação significa que somos capazes de,
em um período de tempo razoável, determinar que as entradas geram os resultados
esperados. Se nossa implementação não permitir isso porque leva muito tempo, preci-
samos alterar a implementação. Mas a essa altura, devemos ter testes para verificar
as entradas e saídas. Quando temos testes em vigor, temos confiança suficiente para
refatorar nosso código e alterar a implementação. Se não fizermos esses testes, estare-
mos colocando em risco o comportamento com o qual realmente nos importamos (as
entradas e saídas).
Embora faça parte do que é chamado de teste não funcional , e geralmentenão o foco
da refatoração, podemos priorizar características de desempenho (e outros aspectos
“não funcionais” do código como usabilidade) tornando-os falsificáveis, assim como a
correção do programa. Em outras palavras, podemos testar o desempenho.
No entanto, até que o desempenho esteja sob alguma estrutura de teste verificável
desse formato, não será considerado “comportamento” que estejamos preocupados
em mudar ou não mudar. Se tivermos testes funcionais implementados, podemos
ajustar nossas implementações livremente até decidirmos sobre algum padrão de de-
sempenho. Nesse ponto, nosso conjunto de testes cresce para abranger características
de desempenho.
Essas coisas podem ser importantes para o seu programa, mas só para ficar claro, a
promessa da refatoração de “não mudar o comportamento” não deve se aplicar a es-
sas situações. Implicações de desempenho sutis e difíceis de controlar devem ser tra-
tadas como uma preocupação separada.
Qual é o ponto de refatoração se o
comportamento não muda?
Agora temos mais dois itens para resolver. Primeiro, por que a qualidade é impor-
tante, no contexto de “fazer as coisas”? E segundo, o que é qualidade e como a refato-
ração contribui para isso?
Pode parecer que todos e todos os projetos operam em um espectro simples entre
qualidade e fazer as coisas.Por um lado, você tem uma base de código “bonita” que
não faz nada de valor. E por outro lado, você tem uma base de código que tenta dar
suporte a muitos recursos, mas está cheia de bugs e ideias incompletas.
Uma metáfora que ganhou popularidade nos últimos 20 anos é a da dívida técnica .
Descrever as coisas dessa maneira coloca o código em uma linguagem pseudofinan-
ceira que os não codificadores podem entender facilmente e facilita uma conversa
mais sutil sobre a rapidez com que as tarefas podem e devem ser feitas.
O espectro acima mencionado de qualidade para velocidade é preciso até certo ponto.
Em projetos pequenos, dívida técnica visível e endereçável pode ser aceitável. À me-
dida que um projeto cresce, no entanto, a qualidade se torna cada vez mais
importante.
Tem havido incontáveis esforços para determinar o que faz um código de qualidade.
Alguns sãodeterminado porcoleções de princípios:
SOLID: Responsabilidade única, aberto/fechado, substituição de Liskov, segregação
de interface e inversão de dependência
SECA: Não se repita
KISS: Seja simples, estúpido
GRASP: Padrões de software de atribuição de responsabilidade geral
YAGNI: Você não vai precisar
Não existe uma grande métrica para a qualidade. Para os propósitos deste livro, có-
digo de qualidade é um código que funciona corretamente e pode ser estendido facil-
mente. A partir disso, nossas preocupações táticas são escrever testes para código e
escrever código que seja facilmente testável. Aqui eu não tão humildementeintroduzir
os princípios EVAN de qualidade de código:
Sinta-se à vontade para criar seus próprios “princípios de qualidade de software” com
seu próprio nome.
Pode-se concluir dessa linha de pensamento que apenas as abstrações mais simples
podem fazer parte de uma base de código de alta qualidade.
Como você resolve uma gama tão ampla de problemas em software e tem tantas fer-
ramentas à sua disposição, seu primeiro palpite raramente é o ideal. Exigir de si
mesmo apenas escrever as melhores soluções (e nunca revisitá-las) é completamente
impraticável.
Com a refatoração, você escreve seu melhor palpite para o código e o teste (embora
não nessa ordemse você estiver fazendo desenvolvimento orientado a testes, ou TDD;
ver Capítulo 4 ). Em seguida, seus testes garantem que, à medida que você altera os
detalhes do código, o comportamento geral (entradas e saídas do teste, também conhe-
cido como interface) permaneça o mesmo. Com a liberdade que oferece, você pode al-
terar seu código, aproximando-se de qualquer versão de qualidade (possivelmente in-
cluindo desempenho e outras características não funcionais) e quaisquer formas de
abstração que achar adequadas. Além do benefício de poder melhorar seu código gra-
dualmente, uma vantagem adicional significativa de praticar a refatoração é que você
aprenderá a errar menos na primeira vez: não por insistir nisso de antemão, mas por
ter experiência em transformar código ruim em bom código.
Portanto, usamos a refatoração para alterar o código com segurança (mas não o com-
portamento), a fim de melhorar a qualidade. Você pode estar se perguntando com ra-
zão como isso se parece em ação. Isso é o que é abordado no restante do livro; no en-
tanto, temos alguns capítulos de antecedentes para passar antes que essa promessa
possa ser cumprida.
Definir exatamente o que é qualidade pode ser difícil em uma linguagem tão ampla
quanto JavaScript, mas com a variedade de habilidades abordadas nestes capítulos,
você deve ficar com muitas opções.
Embora na maior parte deste livro nos comprometamos com a refatoração como um
processo para melhorar o código, não é o único propósito. A refatoração também
ajuda a aumentar a confiança na codificação em geral, bem como a familiaridade com
o que você está trabalhando.
As restrições têm seu lugar e, de muitas maneiras, a falta delas é o que torna o JavaS-
cript tão difícil de aprender e trabalhar. Mas, ao mesmo tempo, a reverência gera res-
trições desnecessárias. Eu vi Ben Folds se apresentar uma vez, e ele terminou o show
jogando sua cadeira no piano. Quem atacaria o piano tradicionalmente reverenciado
(e caro)? Alguém no controle. Alguém mais importante que suas ferramentas.
Você é mais importante que seu código. Quebrá-lo. Apague tudo. Mude tudo o que qui-
ser. Folds tinha dinheiro para um piano novo. Você tem controle de versão. O que
acontece entre você e seu editor não é da conta de mais ninguém, e você está traba-
lhando no meio mais barato, mais flexível e mais durável de todos os tempos.
Por todos os meios, refatore seu código para melhorá-lo quando for mais conveniente
para você. Meu palpite é que isso vai acontecer com frequência. Mas se você quiser
excluir algo que não gosta, ou apenas quebrá-lo ou desmontá-lo para ver como funci-
ona, vá em frente. Você aprenderá muito escrevendo testes e se movendo em peque-
nos passos, mas esse nem sempre é o caminho mais fácil ou mais divertido e liberta-
dor para a exploração.
Antes de terminarmos, vamos mais uma vez distinguir entre refatoração e outros pro-
cessos semelhantes.Aqui está uma lista de coisas que não estão refatorando. Em vez
disso, eles criam novos códigos e recursos:
E a lista continua. Para o código existente, qualquer alteração feita na interface (tam-
bém conhecida como comportamento) deve quebrar os testes. Caso contrário, isso in-
dica baixa cobertura. No entanto, as alterações nos detalhes subjacentes da imple-
mentação não devem interromper os testes.
“ R E FA C TO R I N G ” V S . “ R E FA C TO R I N G ”
Empacotando
Esperamos que este capítulo tenha ajudado a revelar o que é refatoração, ou pelo me-
nos fornecer alguns exemplos do que não é.
Os frameworks não podem nos salvar de nossos problemas de qualidade. jQuery não
nos salvou,e nem ESNext, Ramda, Sanctuary, Immutable.js, React, Elm ou o que vier a
seguir. Reduzir e organizar o código é útil, mas no restante deste livro, você desenvol-
verá um processo para fazer melhorias que não envolvam um ciclo de sofrimento
com baixa qualidade, seguido pelo investimento de um tempo desconhecido para re-
construí-lo no “ Quadro do Mês”, seguido por mais sofrimento nesse quadro, seguido
de reconstrução e assim por diante.
Apoiar Sair