O teu CFO não precisa de perceber acoplamento nem cobertura de testes para tomar uma boa decisão sobre dívida técnica. Precisa de três números: quanto custa a dívida por trimestre, quanto custa corrigi-la e como vais saber que a correção funcionou. A maioria das equipas de engenharia nunca produz esses números, por isso o pedido chega como "precisamos de um sprint de refactoring" e perde para a próxima funcionalidade do roadmap.
Já tens os dados: o histórico do git, os registos dos pipelines de CI e as revisões de incidentes. Este guia transforma-os num modelo de custos que as finanças conseguem verificar, num registo que o mantém atualizado e num caso de uma página para pagar a dívida.
O que conta como dívida e o que não conta
A dívida técnica é um atalho no código que torna o trabalho futuro mais lento ou mais arriscado. Tal como um empréstimo, tem duas partes:
- O capital é o que custaria corrigir o atalho agora: as semanas-engenheiro para substituir as regras fixas no código, acrescentar os testes que faltam ou dividir o módulo.
- Os juros são o que pagas em cada mês em que não o fazes: as horas a mais em cada alteração, os incidentes, as funcionalidades que saem atrasadas.
Chega de duas formas. A dívida deliberada é uma cedência feita de propósito e posta por escrito: "fixamos o IVA no código só para Portugal para lançar em março; revemos antes de vender em Espanha." A degradação acidental não é decisão de ninguém: dependências deixadas a envelhecer, um módulo que cresceu sem dono, um desenho pensado para um décimo do tráfego atual. Ambas custam dinheiro, mas a degradação é a que surpreende os orçamentos, porque ninguém a registou.
Muitas das coisas de que os engenheiros se queixam não são dívida neste sentido:
- Código feio em que ninguém mexe. Se um ficheiro não muda há dois anos, não cobra juros. Deixa-o em paz.
- Funcionalidades em falta. O que o produto ainda não faz é roadmap, não dívida.
- Bugs. Um defeito só se torna sinal de dívida quando a mesma zona não para de os produzir.
- Tecnologia antiga que continua suportada e continua a servir. A idade, por si só, não custa nada.
A regra de que depende o resto deste guia: só se pagam juros onde o código continua a mudar. A tua dívida mais cara não é o teu pior código. Está nos ficheiros que a tua equipa edita todas as semanas.
Um modelo de custos que um CFO aceita
As finanças aceitam um modelo cujos dados de entrada se conseguem seguir até uma fonte. Usa três linhas: fricção, incidentes e atraso. Todos os números que se seguem são um exemplo: substitui cada um pelos teus.
Começa pelo custo-hora total de um engenheiro: salário mais contribuições a cargo da empresa, equipamento, licenças e escritório, a dividir pelas horas realmente disponíveis para trabalho depois de férias e reuniões. As finanças conseguem dar-te este valor. Digamos que é 75 €.
Fricção. Uma equipa de 8 engenheiros perde 4 horas cada um por semana com um único item de dívida: à espera de builds lentos, passagens de regressão manuais, a contornar um módulo em que ninguém se atreve a mexer. Num trimestre de 12 semanas úteis: 8 × 4 × 12 × 75 € = 28.800 €.
Incidentes. Conta apenas os incidentes cuja revisão aponta o item de dívida como causa. Digamos que houve 3 neste trimestre. Cada um levou 12 horas-engenheiro (900 €) e teve 1.600 € de impacto direto no negócio, segundo os teus próprios registos: reembolsos, créditos de serviço, encomendas perdidas durante a falha. São 3 × 2.500 € = 7.500 €. Deixa as horas de incidentes fora da linha de fricção para que nenhuma hora seja contada duas vezes.
Atraso. Uma funcionalidade cujo business case prometia 6.000 € por mês de margem bruta saiu com um mês de atraso, e a equipa consegue mostrar que o atraso veio do item de dívida. São 6.000 €. Usa o valor do business case original, não uma estimativa nova feita para este argumento.
Juros do trimestre: 28.800 € + 7.500 € + 6.000 € = 42.300 €, cerca de 14.100 € por mês.
Agora o capital. Corrigir o item exige 2 engenheiros durante 6 semanas: 12 semanas-engenheiro × 35 horas × 75 € = 31.500 €.
Reclama apenas a redução que vais medir. Digamos que a correção reduz a fricção para metade e acaba com os incidentes: 14.400 € + 7.500 € = 21.900 € por trimestre, ou 7.300 € por mês. O período de retorno é 31.500 € ÷ 7.300 €, pouco mais de quatro meses. Deixa o atraso fora do retorno, porque os atrasos passados não voltam.
Preenche isto com os teus próprios valores:
Friction = engineers x hours lost per week x working weeks x loaded hourly cost
Incidents = incidents linked to the item x (engineer hours x hourly cost + business impact)
Delay = months of delay x monthly value from the feature's own business case
Interest per quarter = Friction + Incidents + Delay
Principal = engineer-weeks to fix x available hours per week x loaded hourly cost
Payback in months = Principal / (interest per month the fix will remove)De onde vêm os números
Cada dado de entrada vem de sistemas que já usas.
Hotspots de alteração a partir do git
Isto conta quantos commits mexeram em cada ficheiro ao longo do último ano:
git log --since="12 months ago" --format= --name-only | grep -v '^$' | sort | uniq -c | sort -rn | head -20Ignora os lockfiles e o código gerado; o resto mostra onde a tua equipa passa o tempo. Mudar muito não é, por si só, dívida, por isso acrescenta dois sinais: quantos desses commits foram correções de bugs e qual o tamanho do ficheiro.
cd "$(git rev-parse --show-toplevel)" || exit 1
since="12 months ago"
git log --since="$since" --format= --name-only | grep -v '^$' | sort | uniq -c | sort -rn | head -20 |
while read -r changes file; do
[ -f "$file" ] || continue
fixes=$(git log --since="$since" -i -E --grep='fix|bug' --format=%h -- "$file" | wc -l)
lines=$(wc -l < "$file")
printf '%7s %5s %7s %s\n' "$changes" "$fixes" "$lines" "$file"
doneAs colunas são alterações, commits de correção, linhas e caminho. Um ficheiro grande que muda todas as semanas e não para de precisar de correções está a cobrar juros. Um ficheiro grande que nunca muda, não. Se tiveres um analisador de complexidade, a pontuação dele é melhor indicador do que o número de linhas.
Conhece os limites da contagem de correções. Depende da disciplina nas mensagens de commit. O padrão também apanha "prefix", "debug" e "fixture". Os squash merges juntam muitos commits num só, e -- "$file" não segue mudanças de nome. Se a tua equipa usa conventional commits, --grep='^fix' é mais preciso. Trata o número como uma ordenação, não como uma medição.
Para transformar hotspots em horas, compara os tempos de ciclo dos tickets: se as alterações ao módulo de preços demoram uma mediana de seis dias e alterações comparáveis noutras partes demoram dois, a diferença é fricção que podes contar.
Duração da CI
Exporta as durações dos pipelines do branch principal do último ano e faz o gráfico da mediana semanal. Põe um preço na espera: se a mediana passou de 8 para 20 minutos, a tua equipa corre 30 pipelines por dia de que alguém fica à espera, e assumes que metade de cada espera se perde na troca de contexto, são 30 × 12 × 0,5 = 180 minutos por dia. São 15 horas por semana, quase 2 das 4 horas por engenheiro do exemplo. A espera da CI é um dado de entrada da fricção, não um custo à parte.
Taxa de falha de alterações e lead time
A taxa de falha de alterações é a proporção de implementações em produção que precisaram de um rollback, de um revert ou de um hotfix. O teu histórico de implementações dá o denominador. Para um limite inferior do numerador, conta os reverts:
git log main --since="3 months ago" --oneline --grep='^Revert "' | wc -lA contagem não apanha os rollbacks feitos ao voltar a implementar uma versão anterior nem as correções publicadas como commits novos. O lead time é o tempo que vai do merge até produção, e os teus jobs de deploy da CI registam-no. Divide as duas métricas por zona: se as alterações a ficheiros hotspot falham ou esperam mais do que o resto, essa diferença são juros.
Tempo de onboarding
Anota a data de entrada de cada engenheiro novo e procura o primeiro commit dele:
git log --reverse --author="new.joiner@example.com" --format='%ad' --date=short | head -1Acompanha isto por pessoa, juntamente com o tempo até mudar um ficheiro hotspot sem pairing. Se não para de crescer, voltas a pagá-lo a cada contratação.
Obtém estes números para o teu próprio código. Pede uma avaliação gratuita de dívida técnica: corremos a análise de hotspots e de frequência de correções nos teus repositórios, olhamos para a tendência de duração da tua CI e para a taxa de falha de alterações, e pomos um preço nos teus principais itens de dívida com o teu próprio custo-hora total.
Mantém um registo de dívida
Os números ficam desatualizados se não viverem em algum lado. Cada entrada precisa de: onde está, um sintoma que qualquer pessoa consiga observar, os juros por mês com a respetiva evidência, um capital estimado, um responsável e uma decisão.
- id: TD-021
where: services/orders/erp-sync/
type: accidental # or: deliberate
recorded: 2026-09-14
symptom: >
Every change to the order export needs a manual end-to-end check;
2 of the last 6 incidents started here.
interest_per_month:
hours: 30
eur: 2250
evidence: hotspot report, incident reviews, ticket cycle time
principal_estimate:
engineer_weeks: 4-6
owner: orders-lead
decision: add contract tests now, then replace the sync job in stages
review: 2026-12-01Para o manter vivo:
- Guarda-o junto ao código, como ficheiro no repositório ou como issues com etiqueta, onde os engenheiros já trabalham.
- Faz a dívida deliberada pagar a entrada. Um atalho tomado de propósito precisa de uma entrada com responsável e data de revisão antes do merge.
- Revê-o todos os meses durante trinta minutos. Volta a correr o script de hotspots, atualiza os juros das primeiras entradas e dá um responsável a cada entrada que não o tenha, ou fecha-a.
- Regista o resultado. Quando um item for pago, escreve o efeito medido ao lado da estimativa. É esse histórico que faz aprovar a proposta seguinte.
Pagar a dívida
Uma parte fixa da capacidade
Reserva uma parte de cada iteração para itens do registo e impede que seja a primeira coisa a ser cortada. Dimensiona-a a partir dos teus próprios juros: se a fricção custa a cada engenheiro 4 de 35 horas por semana, uma parte de cerca de 10 a 15 por cento significa que gastas no capital mais ou menos o que já perdes em juros.
Paga nos hotspots que já estás a alterar
Quando um ticket mexe num dos vinte primeiros hotspots, a estimativa inclui limpar essa zona. O contexto já está carregado e os testes correm de qualquer forma, por isso é a forma mais barata de pagar dívida, e cai exatamente onde estão os juros.
Estrangula as grandes reescritas
Para um módulo demasiado grande para corrigir de uma vez, põe uma fachada à frente e passa para a nova implementação uma rota, uma capacidade ou um segmento de clientes de cada vez. Cada passo chega a produção e pode ser medido, e o código antigo encolhe até poder ser apagado. É assim que uma migração faseada de monólito para microsserviços evita a reescrita de uma só vez, o projeto com mais variância que podes pôr à frente de um CFO.
Trava a dívida nova na revisão
Pagar dívida é inútil se entrar dívida nova ao mesmo ritmo. Põe as regras na CI para não dependerem da disposição de quem revê: testes obrigatórios para o código alterado, atualizações de dependências com calendário e nenhum TODO anónimo. Esta verificação faz falhar um merge request que acrescente um TODO ou FIXME sem ID de ticket (faz primeiro o fetch do branch de destino no job):
diff=$(git diff origin/main...HEAD -U0) || exit 1
if printf '%s\n' "$diff" | grep -E '^\+' | grep -v '^+++' | grep -E 'TODO|FIXME' | grep -vE '(TODO|FIXME)\([A-Z]+-[0-9]+\)'; then
echo "TODO/FIXME without a ticket ID, write it as TODO(PAY-123)"
exit 1
fiOs hábitos de revisão que impedem a dívida de se formar estão nas nossas regras de clean code para equipas em produção.
Apresentar numa página
Leva às finanças uma página por proposta, por esta ordem:
- 1Custo por trimestre. As três linhas, cada uma com a sua fonte: relatório de hotspots, revisões de incidentes, o business case da funcionalidade.
- 2Risco. O que piora se nada mudar: a tendência de incidentes nessa zona, um runtime a aproximar-se do fim de suporte, conhecimento que só uma pessoa tem.
- 3A proposta. O capital como intervalo, pessoas e duração, o que é adiado para o financiar e o ponto em que paras se os números não se mexerem.
- 4Como vais medir o efeito. A linha de base de hoje e as mesmas medidas aos 30, 60 e 90 dias: horas perdidas, incidentes na zona, lead time, duração da CI.
- 5A decisão de que precisas. Uma frase.
O que não dizer a uma audiência de finanças:
- "O código está uma confusão" ou "precisamos de fazer refactoring". Isso descreve a tua frustração, não um custo.
- Story points e velocidade. São unidades internas que as finanças não conseguem auditar.
- "Poupança". Os engenheiros são pagos de qualquer forma. Diz "capacidade devolvida ao roadmap", a não ser que o plano de contratações mude mesmo.
- Médias do setor. Os números dos outros levantam perguntas a que não consegues responder. Os teus próprios dados aguentam-nas.
- Um único valor preciso. Dá um intervalo e explica os pressupostos.
Começa por um item
Não ponhas preço a todo o código. Pega na primeira entrada do relatório de hotspots, passa-a pelo modelo com o teu próprio custo-hora total e leva uma página à tua próxima conversa de orçamento. Se estás a planear novo desenvolvimento web sobre um código que já carrega esta dívida, põe preço à dívida antes de o trabalho novo assentar em cima dela.
Marca uma avaliação gratuita de dívida técnica e vamos correr a análise nos teus repositórios, criar contigo as primeiras entradas do registo e redigir o caso de uma página para o teu item principal, pronto para o teu CFO.