Bug Analysis: tem código no seu repo que não funciona e você não sabe aonde

Os testes passam. O código compila. O comportamento "errado" nunca acontece, então ninguém abre incident. Mas o bug está latente — esperando o caminho certo de execução para se manifestar. Análise estática profunda encontra ele antes.

Tem código no seu repo que nunca pode ser executado. Você não sabe quais. Linhas escritas, revisadas e mergeadas — mas que jamais entram em qualquer caminho real de execução. Bug Analysis é a categoria de análise estática que descobre isso.

TL;DR

Bug Analysis é análise estática focada em erros lógicos: condições impossíveis, dead code, loops sem condição de parada, exceções engolidas. Encontra bugs antes dos testes rodarem — que é onde detectar erro é mais barato. Não substitui testes; complementa.

Para quem  Tech Leads que confiam só em testes Leitura  ~5 min Funil  Awareness → Consideration

What this article explores:

  • Um caso real: um if que nunca pode executar — e quantos casos como esse existem no seu repo
  • A diferença entre Bug Analysis e Code Smells — design ruim vs. erro lógico concreto
  • As três famílias de bugs detectadas por análise de fluxo de dados
  • Por que detectar erro mais cedo é exponencialmente mais barato (custo 1× → 100×)
  • Por que Bug Analysis não substitui testes — e por que complementa
  • A distinção entre risco (bug latente) e defeito (manifestação em produção)
  • Plano operacional em 4 passos para começar hoje
  • Cinco pontos-chave para levar embora
§ 1 Cena

Você herdou um sistema. Em algum lugar dele, existe uma função assim:

JavaScriptO segundo if nunca executa
function processOrder(order) {
  const status = order.status.toUpperCase();

  if (status === 'PENDING') {
    return queue(order);
  }

  if (status === 'pending') {  // ← este bloco nunca executa
    return retry(order);
  }

  return reject(order);
}

O segundo if nunca pode ser verdadeiro. A primeira linha forçou maiúsculas; comparar com lowercase é logicamente impossível. Esse retry(order) nunca foi chamado uma única vez — provavelmente desde o dia que esse código foi escrito.

Quantos casos assim existem no seu repo agora? Sinceramente — você não sabe. Os testes passam. O código compila. O comportamento "errado" nunca acontece, então ninguém abre incident. O bug está latente.

Bug Analysis é a categoria de análise estática que encontra exatamente isso.

Bug Analysis vs. Code Smells: o que muda

Code Smells (do post anterior) são design ruim que aumenta probabilidade de bug.

Bug Analysis encontra bugs lógicos — código que está sintaticamente correto, mas logicamente impossível de fazer o que parece que faz. A diferença:

  Code Smell Bug Lógico (Bug Analysis)
Natureza Padrão de design ruim Erro de lógica concreto
Comportamento Funciona, mas é frágil Não funciona como o autor pensou
Detecção Catálogo de padrões Análise de fluxo de dados
Exemplo Método com 200 linhas if cuja condição sempre é falsa
§ 2 Famílias

Os dois são detectados por análise estática. Mas Bug Analysis exige análise de fluxo de dados (data flow analysis) — algoritmos que rastreiam como uma variável é modificada ao longo da execução para inferir valores possíveis em cada ponto.

O que Bug Analysis tipicamente detecta?

São três famílias principais de erro lógico.

Família 01 Bifurcações impossíveis (dead code)

O exemplo do if que sempre é falso. Variantes incluem:

// Comparação tautológica
if (x > 0 && x < 0) { ... }  // sempre falso

// Variável já fixada
const role = 'admin';
if (role === 'user') { ... }  // sempre falso

// Tipo incompatível
if (typeof n === 'number' && n.startsWith('A')) { ... }
// método não existe em number

O mecanismo: o analisador rastreia o tipo e o conjunto de valores possíveis de cada variável. Quando a condição exige um valor que não pertence ao conjunto, ela é classificada como sempre falsa (ou sempre verdadeira). O bloco correspondente é dead code.

Família 02 Loops sem condição de parada confiável
function findUser(id) {
  let user = repository.firstUser();
  while (user) {  // ← user nunca é reatribuído dentro do loop
    if (user.id === id) return user;
  }
}

O loop continua enquanto user for verdadeiro (ou existir), mas nada dentro do loop muda user. Se firstUser() retorna alguém que tem id diferente do recebido pela função, esse loop nunca termina. Em produção, isso vira CPU 100% e timeout silencioso.

Bug Analysis detecta isso rastreando se a variável de controle do loop pode efetivamente mudar entre iterações.

Família 03 Exceções engolidas
try {
  const result = riskyOperation();
  return process(result);
} catch (e) {
  // silently ignored
}

O catch captura a exceção e não faz nada. Não loga, não relança, não retorna fallback explícito. Do ponto de vista da função, parece que tudo deu certo (porque não vazou exceção), mas process(result) nunca foi chamado e quem chama essa função recebe undefined.

Esse padrão é especialmente perigoso porque mascara a causa raiz de problemas em produção. O sistema "funciona" mas com comportamento errado, e o log não tem rastro.

Detectar erro durante a escrita custa . Detectar em produção custa 100×. Bug Analysis intervém no momento mais barato.

§ 3 Economia

Por que isso é mais barato que descobrir no teste

A justificativa econômica do Bug Analysis é o conceito de shift-left quality: detectar erro o mais cedo possível no ciclo de desenvolvimento.

Fig. 1 — Custo relativo de remediação por etapa do SDLC
 
 
10×
 
30×
 
100×+
 
EscritaBug Analysis no editor
Testes unitáriosCI rápido
IntegraçãoCI estendido
Staging / QAAmbiente de teste
ProduçãoCliente impactado
§ 4 Combinação

(Os números variam por estudo, mas a ordem de magnitude é consistente desde o trabalho clássico de Boehm.)

Bug Analysis roda no editor (via plugin), no commit (via hook) ou no PR (via CI rápido). Encontra o erro antes do teste ser escrito. O autor corrige imediatamente, com o contexto fresco. Não vira ticket, não vira pull request, não vira retrabalho.

Bug Analysis NÃO substitui testes

Importante: Bug Analysis e teste automatizado são complementares, não substitutos.

  • Bug Analysis detecta bugs lógicos visíveis na estrutura do código. Encontra dead code, loops infinitos, exceções engolidas.
  • Testes automatizados verificam que o comportamento implementado corresponde ao comportamento esperado para um conjunto de cenários.

Bug Analysis não sabe se sua função está calculando o desconto certo. Só sabe se a função tem caminhos lógicos impossíveis. Para validar a regra de negócio, você precisa do teste.

A distinção que importa: risco vs. defeito

Da literatura de qualidade de software vem uma distinção útil:

  • Bug lógico (estático) = um risco. Código que é potencialmente errado e pode manifestar problema sob condições específicas.
  • Defeito (em produção) = uma manifestação. O bug latente foi acionado por dados ou caminho real do usuário.

Um bug lógico pode existir por anos sem virar defeito visível — porque o caminho que o ativaria nunca é executado. Mas a sua existência indica código não-determinístico: você não consegue garantir o que ele faz em todos os cenários.

Sistemas com muitos bugs lógicos detectados estaticamente são instáveis — não porque vão quebrar agora, mas porque ninguém sabe quando vão quebrar.

§ 5 IA Generativa

O impacto do Bug Analysis no uso de IA

Bugs lógicos gerados por IA são especialmente perigosos porque passam revisão humana — parecem corretos sintaticamente. Quando o LLM gera uma função, ele otimiza por "código que compila e parece razoável", não por "código com lógica completa". Resultado: condições impossíveis, ramos que nunca executam, exceções engolidas — todos os tipos de bug que análise estática profunda pega entram silenciosamente nos commits gerados por IA.

O que acontece em código bagunçado + IA + sem Bug Analysis

  • Comportamento adicionado em lugares já frágeis. A IA não tem como saber que aquele if no nível 4 nunca executa. Ela adiciona código no caminho morto, pensando que está implementando.
  • Aumento de duplicação com bugs. O LLM gera nova função em vez de reutilizar — e a nova função pode ter os mesmos bugs lógicos da antiga, mas o duplo agora.
  • Maior chance de bugs introduzidos. A IA replica padrões de "tratamento defensivo" que viram exceções engolidas, comparações tautológicas, loops sem progresso. O modelo otimiza por "parecer correto", não por "ser correto".
  • Testes automatizados também escondem bugs. Quando a IA gera teste e código junto, o teste pode estar testando o comportamento bugado — passa verde, mas valida o errado.
O que fazer agora
Plano operacional · 4 passos
  1. 1Rode análise estática focada em bugs no seu repo hoje. SpotBugs (Java), PVS-Studio (C++/C#), ESLint com regras de no-constant-condition e no-unreachable (JS/TS) — ou a plataforma SQA da Codurance que integra Bug Analysis com as outras quatro métricas da série.
  2. 2Triagem de severidade. Priorize bugs lógicos sobre estilo. Dead code e exceções engolidas têm impacto operacional alto.
  3. 3Bloqueie regressão. Configure o gate para que novos PRs não introduzam novos bugs lógicos críticos.
  4. 4Aceite o backlog. Você vai descobrir muitos bugs latentes. Não tente corrigir todos. Corrija os que estão em código quente (mexido recentemente).
Resumo · Pontos-chave
Cinco frases para levar embora.
  • Bug Analysis encontra erros lógicos por análise estática — sem executar código.
  • Detecta três famílias: bifurcações impossíveis, loops sem progresso, exceções engolidas.
  • Não substitui teste — complementa. Encontra bug antes do teste rodar.
  • Mais cedo = mais barato. Custo de correção cresce ordem de magnitude por etapa do SDLC.
  • Bug lógico é risco. Defeito em produção é a manifestação. Eliminar risco antes da manifestação é a estratégia.
Próximo passo

Os quatro posts até aqui (Ciclomática, Cognitiva, Smells, Bugs) tratam de problemas localizados — em uma função, em um arquivo. O próximo post fala da métrica que captura um problema sistêmico: Code Duplication. E é o problema mais perigoso porque ele se espalha sem aparecer no radar.

Code Duplication→

How Codurance can help

A Codurance acompanha times de engenharia que querem instrumentar a saúde do código sem virar gestores. Ajudamos Tech Leads e Staff Engineers a integrar Bug Analysis em pre-commit hooks e PR checks, definir thresholds de severidade e estabelecer processos de triagem que evitam que bugs lógicos virem defeitos em produção.

Se você quer aplicar essas práticas no seu time, entre em contato hoje.