A arte esquecida da refatoração

A arte esquecida da refatoração
Photo by Joshua Hoehne / Unsplash

Numa empresa de software qualquer uma situação como essa já aconteceu:

Gerente: O que você tá fazendo agora?
Programador: Eu tô refatorando essa parte do código…
Gerente: Refatorando? É tipo uma otimização de performance?
Programador: Não, tô só organizando o código.
Gerente: Por que? Tá com bug?
Programador: Não, tô só limpando um pouco o código.
Gerente: E por que você já não fez limpo da primeira vez?!

Quem tá certo nessa história? Onde tá o problema? Pera, existe um problema? Minha missão hoje é trazer alguns pontos importantes sobre a pratica deliberada da refatoração e quem sabe assim você consiga espalhar a mensagem no seu time e, se eu tiver sucesso, irá vender a prática mais gestores.

Refatoração não vende

E não vende em nenhum lugar! Faça uma busca nos canais tech dos influencers e cursos que você verá pouco ou nenhum conteúdo sobre refatoração, em comparação serão trocentos conteúdos sobre a nova lib do momento ou mais um projeto CRUD do zero.

Os cursos e bootcamps não ficam atrás… O que vende é você aprender uma ferramenta nova, um projeto novo pro seu portifolio, é entregar algo concreto, que alguém consegue ver claramente.

Essa prática é completamente fora do mercado de trabalho, principalmente nos estágios iniciais, ou você realmente acha que alguma empresa vai contratar um programador no início de carreira pra começar um sistema novo (do zero) que é basicamente um CRUD? Não, não vai! E se acontecer já é uma red-flag.

O cenário mais comum é você entrar num projeto que já existe, rodando em produção com clientes e você dará manutenção. É isso que vai acontecer, e você deveria se preparar pra esse cenário. E uma das formas para se preparar é aplicando a prática deliberada de refatoração.

No contexto desse artigo eu considerar código limpo sendo o contrário de código sujo, aquele trecho de código que é difícil entender não pela complexidade que o problema exige, mas porque está mal escrito. Fique livre pra usar o sentimento que quiser, WTFMau cheiro... Confio no seu julgamento.

Pratica deliberada

Vamos colocar os pingos nos “i"s.

Pratica deliberada é quando você decide fazer alguma coisa, o contrário é ser levado pela circustância. Por exemplo, quando você separa um espaço do seu dia para uma atividade recreativa, você planeja fazer. A menos que o mundo acabe naquela hora você tá lá imerso na atividade deliberada.

E refatoração é quando você altera a estrutura do código sem alterar o comportamento. A segunda parte é bem importante - sem alterar o comportamento - significa que na refatoração você não se compromete com mais nada além de arrumar um pouco o código.

Manter a refatoração como uma prática deliberada é sobre fazer refatoração como parte da sua rotina, você separa um tempo pra essa atividade e fica imerso apenas nela.

Por que é importante?

Resposta rápida: Porque não fazemos limpo da primeira vez! Simples assim! Aqui tem um espaço pra “engenharia de software de botequim" e podemos passar horas discutindo os porquês, mas não vou entrar nesse tópico.

Dado que não escrevemos limpo da primeira vez precisamos melhorar depois. E o porquê precisamos é onde eu quero focar.

Precisamos melhorar depois porque sempre escrevemos código pra alguém, esse alguém pode ser você amanhã ou o seu time. Queremos deixar as coisas um pouco melhor do que encontramos… Se esse espírito de time não te pega pense pelo lado mais individualista: Quero deixar as coisas melhores pra mim amanhã.

Na busca por ser um rock-star-jedi-matrix-programmer esquecemos do básico, negligenciamos bons hábitos na busca do novo hype. Você não precisa fazer cosplay de Mr. Robot, apenas tenha disciplina para treinar e manter bons hábitos.

Não sou um ótimo programador; sou apenas um bom programador com ótimos hábitos.
Kent Beck.

Ganhando mais conhecimento do código

Quando falo de refatoração deliberada entendo que como qualquer outra habilidade é uma prática, essa prática pode ocorrer algumas vezes na base do sentimento porém também existem técnica para isso. Aqui não quero impor como você vai desenvolver esse habilidade, mas apenas desenvolva.

Um conselho que posso dar é que absorver algumas técnicas, colocar em prática e na sequência absorver mais técnicas me parece ser um ótimo caminho.

Quero compartilhar algumas técnicas que eu uso refatoração para ganhar ou adicionar mais conhecimento sobre o código. São técnicas simples que não tomam tempo e as uso em dois momentos:

Antes de escrever código novo eu começo refatorando, esse hábito me dá um maior entendimento do código, sei com as coisas se conectam e onde estão os pontos fracos (código sujo).

Depois que escrevo o código, quero deixar as coisas um pouco mais claras pro meu eu do futuro e pro time, quero adicionar mais conhecimento no que eu escrevi e facilitar o trabalho do próximo.

Removendo magic number/string.

Quero apenas remover números ou texto que não adicionam muito significado, por exemplo:

Vou sair disso:

if (status === 'pending') {
...
}

Para isso:

if (status === ORDER.PENDING) {
...
}

Posso criar um enum ou um objeto (para linguagens sem enum) e substituir onde houver o status como texto. Com isso eu adiciono um pouco mais de significado ao código e centralizo o status num único local, adiciono facilidade para a próxima pessoa que precisar alterar algo do status do pedido.

Dê novos nomes

Quanto mais tempo ficamos numa tarefa mais ganhamos conhecimento sobre ela, seus detalhes, suas interações. É muito comum começarmos com um entendimento ok e irmos evoluindo com o passar do tempo.

Essa técnica é simples, reviso os nomes usados no início e quando necessário troco por nomes que aumentam o entendimento.

Nem sempre vamos conseguir dar novos nomes, as vezes o custo é muito alto, funções que estão espalhadas pelo código exigem mudanças mais severas, nesse caso eu apenas aceito e sigo em frente. Dar novos nomes é eficaz no fim da tarefa, onde você pode revisitar o seu próprio código adicionando mais conhecimento.

Extração de função

Essa técnica é bem batida e antiga (fazer o básico é importante), é quando extraímos uma função e levamos para outro lugar, pode ser uma classe, módulo. O objetivo é que esse novo lugar adicione mais conhecimento para os próximos que irão passar por ali, ou em termos mais técnicos, estamos criando algo mais coeso.

O maior motivo que me faz escrever essa técnica aqui é com o foco em programadores React, essa técnica brilha muito quando extraímos a lógica dos componentes em hooks separados, o próprio nome do hook já ajuda para adicionarmos mais conhecimento ao código.

Note que aqui não estou falando para separar em hooks para reaproveita-los, isso geralmente é uma falácia, hooks que são reutilizáveis devem nascer assim desde o primeiro dia e exigem um grau de complexidade e maturidade mais elevados, também tomam mais tempo. Aqui quero apenas facilitar o entendimento dos outros, apenas isso. Diminua um pouco as ilusões de grandezas em criar hooks super reaproveitáveis, esse não é objetivo aqui.

Remover ternários “malucos"

Ternário, para mim, é um caso onde a intenção foi boa, porém o dia a dia transformou num completo desastre em alguns casos. Ternário não é uma simplificação de if/else, ternário é um operator baseado em if/else. If/else são estados da sua aplicação.

Ou seja, quero usar o ternário quando quero operar com valores diferentes dado o estado da minha aplicação. Novamente escrevo essa técnica para os programadores React e seus ternários no JSX.

Quero sair disso:

function Component () {

return (<div>
 {status === ORDER.PENDING ? (
   <div>
       ...UMAS 10 LINHAS...
    </div>):
   (<div>
      ...MAIS 10 LINHAS...
    </div>)}
  </div>)
}

Para isso:

function Component () {

if (status === ORDER.PENDING) {
 return (
       <div>
       ...UMAS 10 LINHAS...
       </div>
  )

 if (!status === ORDER.PENDING) {
   return (
      <div>
       ...MAIS 10 LINHAS...
      </div>
    ) 
  }
}

Se tenho mais código antes e depois do ternário posso simplesmente extrair o ternário (4.3) num componente separado.

Uma ferramenta para ajudar na refatoração

Para fechar vou passar uma ferramenta que vai ajudar muito na refatoração, ela vai dar mais robustez e confiança.

Teste automatizado!

Simples e básico! Eu prefiro testes de unidade, posso escreve-los antes ou depois, mas quando eu tenho testes eles agem como um robozinho rigoroso que estará pronto pra apontar o menor erro. Quando tenho bons testes consigo refatorar sem medo de ser feliz.

Saiba parar

Tão importante quanto melhorar um pouco as coisas é saber quando parar, não ficar num limbo de preciosismo. Refatoração irá dar suporte para simplificar as coisas que dará suporte para boa manutenção que dará suporte para entregas de valor constantes.

Precisamos domar nossa vontade de ficar polindo o código ao extremo, escrevo código para apoiar o negócio e não mantemos um negócio para apoiar o código. Cada uma vai desenvolver um tempo limite para essa refatoração que adiciona conhecimento, porém eu não recomendo que se gaste mais que uma hora ou 10% do tempo total da tarefa nisso, se esse for o caso o melhor é separar um tempo maior e isolado para melhorias no código.

Com prática deliberada e constante você poderá gastar poucos minutos em refatoração. O seu eu do futuro e seu time agradecem!