Toda Reescrita Ia Ser a Última

Reescrevi o mesmo componente central do meu sistema três vezes. Não remendei, não refatorei — reconstruí, quase do zero, três vezes distintas. E a cada uma delas, eu tinha certeza de que esta versão era a verdadeira: a arquitetura limpa e correta sobre a qual eu finalmente iria construir de vez.

Eu estava errado três vezes seguidas, com plena confiança em cada uma. Estar errado era irritante. A plena confiança é a parte sobre a qual eu realmente quero falar, porque era a mesma sensação se repetindo, e nem uma vez sequer eu a reconheci como um aviso.

”Desta vez está certo”

Existe um barato específico que vem com uma reescrita do zero. O código antigo é uma bagunça — você consegue ver cada concessão, cada remendo, cada lugar onde a realidade te forçou a ceder. O novo design, repousando limpo na sua cabeça, não tem nada disso. Ele é elegante. Ele é óbvio. Ele é claramente melhor.

Então você derruba a coisa antiga e constrói a nova, e por um tempo parece progresso, porque o novo código realmente é mais limpo. Aí você começa a usá-lo, e o ceder começa de novo, e algum tempo depois você está parado diante de uma segunda bagunça, sentindo exatamente a mesma coceira de começar tudo de novo.

Por que a reescrita sempre parece melhor

A comparação é viciada, e foram precisas três rodadas para eu enxergar como. Quando você julga uma reescrita, está comparando um design fresco e idealizado contra um antigo que passou meses absorvendo o atrito do uso real. Claro que o novo parece melhor. Ele ainda não encontrou nenhum dos problemas.

O código antigo parece feio não só porque foi imperfeitamente projetado, mas porque ele está vestindo a sua experiência. Muitas das ramificações estranhas nele são cicatrizes de casos extremos reais — coisas que o mundo jogou nele e que o novo design limpo simplesmente nunca precisou sobreviver. Você nem sempre está comparando um bom design com um ruim. Muitas vezes você está comparando um veterano com um recruta e ficando impressionado com o quão sem cicatrizes o recruta é.

O custo que eu continuava pagando

Cada reescrita jogava fora mais do que código. Ela jogava fora conhecimento — o tratamento acumulado e arduamente conquistado de todas as situações estranhas com que a versão antiga havia silenciosamente aprendido a lidar. E porque esse conhecimento vivia no código em vez de na minha cabeça, reconstruir significava redescobri-lo: bater nos mesmos casos esquisitos de novo, depurar os mesmos problemas de novo, pagar uma segunda e uma terceira vez por lições que eu já havia comprado.

Existe um tipo particular de exaustão em corrigir um bug e perceber que você já corrigiu este exato bug antes, em uma versão do código que não existe mais. Foi disso que se tratou boa parte da minha terceira reescrita — reconquistar lentamente o conhecimento que eu havia jogado fora na segunda.

A coisa por baixo: abstração prematura

O verdadeiro motor de toda essa reconstrução era um erro em como eu pensava sobre design. Eu continuava reescrevendo porque continuava tentando encontrar a estrutura certa antes de realmente entender o problema. Eu tratava a abstração correta como algo que eu poderia sentar e projetar corretamente de antemão, se eu fosse apenas esperto o suficiente.

Na minha experiência, abstrações úteis raramente eram projetadas corretamente de antemão; elas eram conquistadas através do uso. Elas vêm de conviver com o problema por tempo suficiente para aprender onde ele de fato cede — quais partes variam e quais permanecem fixas, onde estão as verdadeiras junções. Projetá-la inteiramente de antemão é adivinhar, e cada reescrita era apenas eu adivinhando de novo, ligeiramente mais bem informado, mas ainda bem antes de eu ter aprendido o suficiente para adivinhar bem.

Quando uma reescrita de fato vale a pena

Não quero alegar que reescritas estão sempre erradas. Às vezes um design genuinamente não consegue se esticar até onde você precisa que ele vá, e evoluí-lo no lugar custaria mais do que começar do zero. A distinção que eu acabei aprendendo a traçar é sobre a origem do impulso.

Uma reescrita movida por um genuíno novo entendimento do problema — “agora vejo que esta coisa que eu tratava como um conceito são na verdade dois” — costuma ser progresso real. Uma reescrita movida principalmente por desconforto com o código atual — “isto é feio, eu quero algo limpo” — é mais frequentemente movimento vestindo uma camada nova de tinta. A primeira tem mais probabilidade de produzir progresso estrutural significativo. A segunda mais que tudo muda como você se sente em relação a ele por algumas semanas, até que a coisa nova também fique feia.

A solução: dobre no lugar, até você realmente não conseguir

O hábito que eu construí foi rebaixar a reescrita de primeiro instinto a último recurso. Diante de uma estrutura que me incomoda, agora eu tento primeiro mudá-la no lugar — remodelá-la, refatorá-la, deixá-la manter seu conhecimento acumulado enquanto eu a movo em direção ao que preciso. Eu tento reservar uma reconstrução completa para quando a estrutura existente genuinamente luta contra toda tentativa de evoluí-la, e não meramente quando ela ofende meu senso de arrumação.

Boa parte do tempo, o desconforto que te faz querer começar do zero é informação, não um veredito. É o código te dizendo onde dói — e isso é exatamente o conhecimento que você jogaria fora ao reconstruir do zero.

A certeza era o sinal

O fio que percorria todas as três reescritas não era código ruim. Era um sentimento: a limpa e total certeza de que desta vez eu havia acertado. “Esta é a arquitetura final” era a frase que eu dizia, na prática, antes de cada uma. O fato de uma frase continuar se revelando errada deveria reduzir sua confiança nela, e aos poucos reduziu.

Forte certeza sobre um design que você ainda não submeteu a teste de estresse não é o mesmo que percepção. Frequentemente é apenas a ausência das cicatrizes que teriam te ensinado o contrário — a confiança confortável de um plano que ainda não encontrou o mundo. Hoje em dia, quando eu sinto absoluta certeza de que um novo design é o final, eu tento tratar o próprio sentimento como uma pista de que talvez eu não tenha convivido com o problema por tempo suficiente para que se confie em mim com essa opinião.

— Sem sinais, sem retornos, isto não é aconselhamento de investimento.