O que é dívida técnica no software: guia para devs solo

Resumo

Dívida técnica é o custo acumulado de atalhos tomados para entregar mais rápido. Existem quatro tipos: código, documentação, segurança e tooling. Para builders solo, alguma dívida é deliberada e correta. A chave é tornar a dívida visível com um arquivo simples, pagar continuamente usando a Regra do Escoteiro e priorizar pelo raio de impacto. Ferramentas como SonarQube e CodeScene ajudam a detectar o que você não vê.

Um desenvolvedor solo numa mesa cheia de monitores mostrando código complexo à noite

Se você pesquisou "o que e divida tecnica software", a resposta direta é: dívida técnica é o custo acumulado de cada atalho que você tomou para entregar mais rápido. O termo foi cunhado por Ward Cunningham em 1992 como metáfora financeira: pede emprestado agora, paga os juros depois. O que a diferencia de código ruim comum é a intenção: uma troca, consciente ou não, entre velocidade de curto prazo e sustentabilidade a longo prazo.

Se você já deixou um comentário TODO num arquivo, hardcoded um valor porque precisava entregar na sexta-feira, ou copiou e colou uma função em vez de extrair um módulo compartilhado, você já assumiu dívida técnica. A maioria dos projetos pessoais é construída sobre ela, e a maioria dos devs solo carrega mais do que percebe.

Por que builders solo acumulam dívida mais rápido do que equipes

Equipes têm fricção embutida. Revisões de código, discussões de arquitetura, documentos de padrões: essas coisas desaceleram o desenvolvimento, mas também desaceleram o acúmulo de dívida. Como dev solo, você não tem essa fricção. Cada trade-off é sua decisão, em tempo real, às 23h quando você só quer ver a parada funcionar.

O resultado é uma codebase que reflete cada concessão feita sob pressão de tempo. Isso não é um defeito de caráter. É a realidade estrutural de construir sozinho. O problema é que a dívida se acumula com juros compostos. Uma API key hardcoded é uma hora de trabalho para corrigir. Quando você tem vinte delas espalhadas por seis arquivos porque o padrão se propagou, é um dia inteiro de arqueologia antes de sequer começar a resolver.

Existe também uma forma mais sutil de acúmulo: a dívida arquitetural de decisões tomadas quando o projeto era pequeno e que não sustentam quando o projeto ganha tração. Um arquivo JSON plano como banco de dados está ótimo com zero usuários. É um problema com quinhentos. Devs que tocam projetos paralelos junto com trabalho fixo enfrentam isso constantemente: otimizar para velocidade de entrega, absorver a dívida, renegociar depois, se houver um "depois".

Os quatro tipos de dívida técnica que realmente importam

Nem toda dívida é igual. Aqui está uma análise prática para projetos pessoais especificamente.

Dívida de código é a mais comum. Cobre atalhos no próprio código: lógica duplicada, funções que fazem coisas demais, variáveis chamadas temp2 que ainda estão lá seis meses depois. Essa é a dívida que você sente toda vez que vai adicionar uma funcionalidade e passa trinta minutos só entendendo o que o código existente faz antes de conseguir mudar qualquer coisa.

Dívida de documentação é subestimada por builders solo porque não tem mais ninguém para confundir. Aí você tira três semanas do projeto, volta, e passa quatro horas descobrindo por que construiu a API daquela forma específica. Você agora está confuso com suas próprias decisões de dois meses atrás. A suposição de que você vai lembrar o contexto está quase sempre errada.

Dívida de segurança se acumula quando você pula validação de inputs, deixa rotas de admin desprotegidas durante o desenvolvimento e esquece de fechar, ou continua rodando uma biblioteca que teve uma vulnerabilidade crítica corrigida seis versões atrás. Em projetos pessoais, isso geralmente parece baixo risco até você ter usuários reais, e aí não é mais teórico.

Dívida de tooling é a que os builders menos discutem. Sem pipeline de deploy. Passos manuais para fazer release. Um arquivo .env que só existe no seu computador sem formato documentado. Quando algo quebra em produção, essa é a dívida que transforma uma correção de trinta minutos numa recuperação de três horas onde você também está reconstruindo o contexto de como qualquer coisa é deployada.

Quatro categorias de dívida técnica ilustradas com post-its coloridos num workspace de desenvolvedor

Quando assumir dívida é a decisão certa

Voilà o que trava na prática: a literatura de software corporativo trata a dívida como uniformemente ruim. Para um builder solo ou indie hacker, alguma dívida é a decisão correta.

Você tem um projeto pessoal que quer validar em duas semanas. Escrever uma suíte de testes completa antes de saber se aquilo tem algum usuário não é disciplina de engenharia, é procrastinação com nome respeitável. Pular testes com zero usuários e adicioná-los quando tiver dez clientes pagantes é um trade-off deliberado e razoável. O próprio Ward Cunningham chamou isso de dívida "prudente e deliberada": você sabe que está assumindo, entende as consequências e planeja pagar de volta.

O problema é quando builders assumem dívida sem perceber, ou assumem deliberadamente e nunca planejam o pagamento. Dívida sem plano é só entropia.

A regra que funciona na prática: dívida está bem quando é limitada. Um valor de configuração hardcoded é administrável. O mesmo padrão aplicado em trinta arquivos diferentes é uma codebase onde ninguém consegue trabalhar, incluindo você. A maioria dos builders solo não rastreia a própria dívida. Ela existe como um desconforto vago na cabeça. Esse é o problema real, não a dívida em si, mas a falta de visibilidade sobre o que ela realmente é e quanto vai custar para resolver.

Como ver sua dívida antes de ela começar a custar caro

A forma mais barata de gerenciar dívida é torná-la visível. Isso não exige um processo complexo. Um arquivo simples DIVIDA.md na raiz do seu repositório onde você anota os trade-offs conforme os faz leva trinta segundos por entrada e poupa horas de redescoberta depois.

Uma entrada típica pode ser assim:

## [2026-08-03] String de conexão DB hardcoded em api/users.ts
Por que: Precisava entregar a demo na sexta.
Custo: Específico de ambiente, quebra se qualquer outra pessoa tentar rodar localmente.
Correção: Mover para variável de ambiente com dotenv. Estimativa: 20 min.
Prioridade: Alta, antes de qualquer colaborador entrar.

Isso é tudo. O formato não importa. O ato de escrever importa porque te força a articular o trade-off explicitamente em vez de deixá-lo evaporar no código onde vai silenciosamente acumular juros.

Ferramentas de análise estática fazem uma versão diferente disso automaticamente. Ferramentas como SonarQube ou CodeClimate varrem sua codebase e sinalizam code smells, duplicações, pontos críticos de segurança e pontuações de complexidade. São mais úteis para capturar dívida que você não sabia que estava criando, o tipo inadvertido que vem de um padrão que você não percebeu estar aplicando doze vezes seguidas.

CodeScene vai um passo além ao analisar o histórico de commits para identificar quais arquivos mudam juntos e quais hotspots são tocados repetidamente sob pressão de tempo. Para um projeto solo, esse tipo de sinal é mais acionável do que um snapshot estático: mostra onde você tem feito concessões repetidamente, não apenas onde o código parece ruim agora.

Três formas de pagar a dívida sem parar de construir

O erro é tratar o pagamento de dívida como um sprint dedicado que você agenda para o próximo mês e nunca chega. A abordagem correta é pagar continuamente em pequenas quantidades, embutido no fluxo normal de trabalho.

A Regra do Escoteiro aplicada ao código: deixe o arquivo que você editar um pouco melhor do que encontrou. Renomeie a variável confusa enquanto já está nela. Extraia a lógica duplicada para uma função enquanto já está tocando nela. Isso custa de cinco a quinze minutos por sessão e se acumula significativamente ao longo de meses de trabalho consistente.

Orçamento de dívida durante o desenvolvimento ativo: se você está construindo uma nova funcionalidade, aloque 20% do tempo para corrigir dívida no código adjacente. Não dívida descoberta em partes distantes da codebase, isso pode esperar. Dívida que toca diretamente no que você está construindo agora. Isso evita o padrão comum onde novas funcionalidades pioram a dívida antiga porque são construídas em cima dela.

Triagem por raio de impacto: nem toda dívida merece atenção igual. Dívida em código que você toca toda semana importa mais do que dívida em um módulo que você não abriu em quatro meses. Ao decidir o que endereçar, pergunte: se isso quebrar ou precisar mudar, quantas outras coisas afeta? Alto raio de impacto, alta prioridade. Dívida de baixo raio que vive num canto raramente visitado pode ficar lá.

Uma regra de três para um funciona para desenvolvimento ativo: para cada três sessões construindo novas funcionalidades, dedique uma sessão pagando dívida. Isso mantém a proporção sob controle sem parar o progresso.

Desenvolvedor revisando e refatorando código num home office tranquilo

O que sua dívida atual está te dizendo

Aos seis meses de projeto, a distribuição de dívida na sua codebase é um mapa bastante preciso das decisões tomadas sob pressão. Alta dívida no módulo de autenticação significa que você estava com pressa quando construiu. Duplicação massiva na camada de API significa que você estava validando funcionalidades rapidamente e não parou para consolidar. Complexidade densa num arquivo específico geralmente significa que aquele arquivo virou um depósito quando a arquitetura era incerta.

Essa é uma informação genuinamente útil. Mostra quais partes da sua codebase foram construídas com confiança e quais com incerteza. As partes construídas com incerteza também costumam ser as partes que se mostraram irrelevantes: funcionalidades que você validou rapidamente e depois despriorizou. A dívida acumulada ali pode nunca precisar ser paga porque aqueles caminhos não levam a lugar nenhum.

As partes que se mostraram relevantes, fluxos centrais de usuário, modelo de dados, contratos de API, autenticação, são onde o pagamento de dívida realmente compensa. Você não está tentando escrever código perfeito em todo lugar. Está tentando identificar as paredes estruturais e mantê-las limpas.

Se sua codebase chegou ao ponto onde adicionar qualquer funcionalidade leva mais tempo depurando comportamento existente do que escrevendo código novo, esse é o sinal. Não um sinal para parar e reescrever tudo, isso quase nunca é a decisão certa e estima-se que leve o dobro do tempo que você imagina. É um sinal para dedicar as próximas três ou quatro semanas à redução de dívida direcionada nos módulos específicos causando o lentidão.

Reescrever ou refatorar as partes confusas?

Essa é a pergunta que builders solo enfrentam quando a dívida começa a parecer incontrolável. A resposta é quase sempre refatorar, não reescrever.

Reescritas levam metade do tempo que realmente levam. Elas também perdem o conhecimento acumulado embutido no código existente: os casos extremos tratados, os bugs corrigidos, as soluções para peculiaridades de APIs de terceiros descobertas da forma difícil. Você paga a dívida original duas vezes: uma quando a carregou, e outra quando precisa redescobrir tudo enquanto reconstrói.

Refatoração funciona quando é direcionada. Escolha o módulo causando a dor mais concreta, o mais lento para mudar, o que mais origina bugs, o mais difícil de entender. Tenha um quadro completo do que ele faz antes de mudar qualquer coisa. Adicione testes nas fronteiras para poder refatorar com segurança sem quebrar comportamento adjacente. Faça as mudanças incrementalmente ao longo de várias sessões, não numa longa maratona heroica que deixa as coisas pela metade se você ficar sem energia.

Três razões para refatorar, uma razão para não fazer: refatore quando a dívida está numa área de alto tráfego da codebase, quando você está prestes a construir em cima dela, ou quando está causando bugs reais. Pule a refatoração quando o módulo está estável, raramente muda e a dívida é autocontida. Não é uma ideia perfeita. É uma ideia viável: a versão sustentável do gerenciamento de dívida técnica não é dívida zero. É dívida que você entende, consegue articular e está ativamente decidindo carregar ou pagar. Essa clareza é o objetivo real.

Perguntas frequentes

O que é dívida técnica em palavras simples?
É o custo futuro dos atalhos que você tomou hoje para entregar mais rápido. Funciona como dívida financeira: quanto mais tempo você carrega sem pagar, mais 'juros' paga em velocidade de desenvolvimento perdida e tempo gasto depurando.
A dívida técnica sempre precisa ser paga?
Não. Dívida em módulos estáveis que raramente mudam pode ficar indefinidamente. Concentre o esforço de pagamento onde há alto raio de impacto: autenticação, modelo de dados, código que você toca toda semana.
Quanto de dívida técnica é aceitável num projeto solo?
Qualquer quantidade que você consegue articular e rastrear. O problema não é a quantidade, é a invisibilidade. Dívida que você não consegue listar não pode ser gerenciada. Um arquivo DIVIDA.md simples resolve isso.
SonarQube funciona para projetos pessoais pequenos?
Sim. A versão Community é gratuita e cobre análise estática básica. Para projetos muito pequenos, um arquivo DIVIDA.md manual pode ser mais acionável do que um scanner completo, porque captura a intenção além do sintoma.
Qual a diferença entre refatorar e reescrever?
Refatorar muda a estrutura interna preservando o comportamento externo, de forma incremental. Reescrever começa do zero e perde o conhecimento acumulado no código existente. Refatoração é quase sempre a escolha certa para projetos solo.
Como saber quando a dívida técnica está fora de controle?
Quando adicionar qualquer nova funcionalidade leva mais tempo depurando comportamento existente do que escrevendo código novo. Esse é o sinal concreto para um período dedicado de três a quatro semanas de redução de dívida.
O que é a Regra do Escoteiro no contexto de código?
Deixar o arquivo que você editar um pouco melhor do que encontrou. Renomear uma variável confusa, extrair uma função duplicada, remover um TODO já resolvido. Pequenas melhorias contínuas que se acumulam ao longo de meses de trabalho consistente.