Você está na página 1de 14

Capítulo 1. O que é refatoração?

Refatorar não é mudar o código.

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:

Como você garante que o comportamento não muda?


Qual é o sentido de mudar o código se o comportamento não mudar?

No restante do capítulo, buscaremos as respostas a essas perguntas. Não vamos per-


correr a história completa do JavaScript, pois isso já é amplamente abordado na web.

Como você pode garantir que o


comportamento não mude?

Sem qualificação, a resposta a essa pergunta é que é incrivelmente difícil. Felizmente,


muitos tiposde comportamento não são nossa principal preocupação ao refatorar.
Abordaremos estes a seguir:

Detalhes de implementação
Comportamento não especificado e não testado
atuação

A resposta mais curta, para nós, é usar testes e controle de versã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.

A abordagem de Fowler se afasta da automação, ao mesmo tempo em que enfatiza a


“mecânica” da refatoração: etapas de alteração de código que minimizam estados
inseguros.

Se confiássemos em uma abordagem automatizada “Opdykian” para este livro, as fer-


ramentas nos atrasariam significativamente. E também estamos nos desviando da ên-
fase de Fowler na mecânica (processos passo a passo). A razão é que, à medida que
avançamos em direção à confiança em nosso código por meio de uma determinada
refatoração, se ele for apoiado por testes, a verificação do sucesso de nossas altera-
ções deve ser simples. E quando falhamos em executar uma refatoração correta-
mente, o controle de versão (estamos usando o Git) deve nos dar uma maneira fácil de
simplesmente “voltar” para o estado do código de antemão.

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.

Nosso objetivo aqui é tirar os desenvolvedores de JavaScript da lama. Embora seja


tentador tentar automatizar e mecanizar esse processo, a parte mais valiosa do traba-
lho dos gigantes (Opdyke, Fowler, Johnson, et al.) cujos ombros este livro humilde-
mente se apoia é que eles nos deram uma nova mentalidade em torno tornar o código
melhor e fazê-lo com segurança.

Por que não nos importamos com os detalhes da


implementação?

Digamos que temos uma função simplesque multiplica os números por 2:

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){

return number << 1;

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

Se você estiver testando detalhes de implementação extremamente específicos, em al-


gum momento você nãoestar testando seu programa, mas sim o próprio ambiente.
Veremos o teste em detalhes mais tarde, mas, por enquanto, você pode executá-lo em
um console de nó ou salvando-o em um arquivo e executando . Dito isto, não é crítico
fazê-lo neste momento. node file_name.js

Digamos que você esteja testando algo assim:

assert = require('assert');

assert(2 + 2 === 4);

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');

assert(.first([3, 2]) === 3);

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:

function doesThings(args, callback){

  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.

Mas no contexto de refatoração, não nos importamos se esse comportamento ainda


muda, porque não iremos refatorá-lo . Quando temos algum código que carece de tes-
tes (ou pelo menos uma forma documentada de executá-lo), não queremos alterar
esse código. Não podemos refatorá-lo , porque não poderemos verificar se o comporta-
mento não muda. Mais adiante no livro, abordaremos a criação de “testes de caracte-
rização” para lidar com código não testado.

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

“Eu refatorei o login para obter o endereço de e-mail e o nome de usuário.”

"Não, você não fez."

“Estou refatorando o código para ____”

“Não, você não é.”

“Antes de podermos adicionar testes, precisamos refatorar.”

"Não."

“Refatorando o–”

"Não."

“Refa–”

"Não."

Por que não nos preocupamos com o desempenho?

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.

O desempenho é privilegiado entre os aspectos não funcionais de uma base de código,


pois é relativamente fácil elevar a um padrão semelhante de correção. Ao “benchmar-
king” nosso código, podemos criar testes que falham quando o desempenho (por
exemplo, de uma função) é muito lento e passam quando o desempenho é aceitável.
Fazemos isso tornando a própria execução da função (ou outro processo) a “entrada”
e designando o tempo (ou outro recurso) tomado como “saída”.

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.

Então, no final, se preocupar com o desempenho (e outros aspectos não funcionais) é


uma preocupação secundária até que decidamos criar expectativas e testes em torno
disso.

DIFICULDADES PARTICULARES DO JAVASCRIPT COM DESEMPENHO

Para alguns tipos de JavaScript (consulte o Capítulo 2 ), será completamente impossí-


vel alterar (inseguro) ou refatorar (seguro) seu código sem alterar o desempenho. Adi-
cionar algumas linhas de código front-end que não são minimizados aumentará o
tempo de download e processamento. A incrível quantidade de ferramentas de com-
pilação, compiladores e implementações pode realizar vários truques devido à forma
como você estruturou seu código.

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?

O objetivo é melhorar a qualidade preservando o comportamento.Isso não quer dizer


que corrigir bugs em código quebrado e criar novos recursos (escrever novo código)
não sejam importantes. Na verdade, esses dois tipos de tarefas estão mais intima-
mente ligados aos objetivos de negócios e provavelmente receberão muito mais aten-
ção direta dos gerentes de projeto/produto do que preocupações sobre a qualidade da
base de código. No entanto, essas ações são sobre a mudança de comportamento e,
portanto, são distintas da refatoração.

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?

Equilibrar a qualidade e fazer as coisas

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.

O que é qualidade e como ela se relaciona com a


refatoração?

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

Existem métricas como cobertura de código/teste, complexidade, número de argu-


mentos e comprimento de um arquivo. Existem ferramentas para monitorar erros de
sintaxe e violações do guia de estilo. Algumas linguagens chegam a eliminar a possibi-
lidade de certos estilos de código serem escritos.

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:

Extrair funçõese módulos para simplificar interfaces


Verifique o comportamento do código por meio de testes
Evite funções impuras quando possível
Nomeie bem as variáveis ​e funções

Sinta-se à vontade para criar seus próprios “princípios de qualidade de software” com
seu próprio nome.

LEGIBILIDADE HUMANA COMO QUALIDADE

A “legibilidade humana” às vezes é citada como a principal preocupação com a quali-


dade, mas essa é uma métrica bastante intratável. Os seres humanos vêm com experi-
ências variadas e exposição a conceitos. Novos codificadores, ou mesmo experientes
em um novo paradigma ou base de código, podem ter dificuldadescom abstrações, de-
vidamente aplicadas ou não.

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.

Na prática, as equipes encontram um equilíbrio entre evitar o uso de recursos esotéri-


cos e confusos e reservar um tempo para orientar os membros juniores para entender
abstrações bem aplicadas e sensatas.
No contexto da refatoração, a qualidade é o objetivo.

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.

O Capítulo 2 fornece informações básicas sobre o próprio JavaScript. Os capítulos 3 e


4 dão uma justificativa para testes, seguida por uma abordagem acionável para testes,
derivada de inclinações naturais para escrever código com confiança e iterar rapida-
mente, em vez de uma insistência dogmática em testar simplesmente sendo enten-
dido como algo inquestionavelmente bom e apropriado. O Capítulo 5 explora a quali-
dade em profundidade, auxiliado por visualizações de funções chamadas diagramas
Trellus , sobre os quais você pode aprender mais em trell.us .

Nos Capítulos 6 e 7 , veremos técnicas gerais de refatoração. Em seguida, veremos a


refatoração de código orientado a objetos com hierarquias no Capítulo 8 e padrões no
Capítulo 9 . Em seguida, terminamos com a refatoração assíncrona ( Capítulo 10 ) e a
refatoração por meio de programação funcional ( Capítulo 11 ).

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.

Refatorando como Exploração

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.

O que é e não é refatoraçã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:

Adicionando a funcionalidade de raiz quadrada a um aplicativo de calculadora


Criando um aplicativo/programa do zero
Reconstruindo um aplicativo/programa existente em uma nova estrutura
Adicionando um novo pacote a um aplicativo ou programa
Dirigindo-se a um usuário pelo nome e sobrenome em vez do nome
Localizando
Otimizando o desempenho
Convertendo código para usar uma interface diferente (por exemplo, síncrono
para assíncrono ou retornos de chamada para promessas)

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.

Adicionalmente,quaisquer alterações de código feitas sem testes em vigor (ou pelo


menos um compromisso de testar manualmente o código) não podem garantir a pre-
servação do comportamento e, portanto, não são refatoração, apenas alteração de
código.

“ R E FA C TO R I N G ” V S . “ R E FA C TO R I N G ”

Inicialmente para este livro, consideramos designar “refactoring”, como é coloquialmente


usado para significar “alteração de código”, por um r minúsculo , e reservando a versão em
maiúscula para nossa definição mais específica (reestruturação de código com confiança de
forma que preserve o comportamento) . Como isso é complicado e nunca nos referimos à “refa-
toração” de letras minúsculas no contexto deste livro, decidimos não usar essa distinção. No en-
tanto, quando você ouve alguém dizer “refactoring”, vale a pena parar para considerar se eles
querem dizer “Refactoring” ou “refactoring” (ou seja, reestruturação ou apenas alteração de
código).

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 é.

Se pudéssemos definir e alcançar código de qualidade por meio da refatoração em Ja-


vaScript no resumo ou simplesmente olhando para exemplos inspiradores de outras
linguagens (principalmente Java), nossas bases de código JavaScript não sofreriam
com a dicotomia “quebrada ou nova” de hoje, onde as bases de código são mal manti-
dos até serem reescritos usando a ferramenta A ou a estrutura B: uma abordagem
cara e arriscada.

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

© 2022 O'REILLY MEDIA, INC.  TERMOS DE SERVIÇO POLÍTICA DE PRIVACIDADE

Você também pode gostar