Dicas para configurar breakpoints condicionais e logpoints em debuggers

1. Fundamentos dos Breakpoints Condicionais

Breakpoints condicionais são uma ferramenta essencial para depuração eficiente. Diferentemente dos breakpoints simples, que interrompem a execução em toda iteração, os condicionais permitem pausar apenas quando uma expressão específica é verdadeira.

Quando usar cada um:
- Breakpoints simples: ideais para poucas iterações (até 10) ou quando você precisa inspecionar cada execução manualmente.
- Breakpoints condicionais: indispensáveis em loops com centenas ou milhares de iterações, ou quando apenas estados específicos interessam.

Sintaxe básica de condições:

// Exemplo em JavaScript
// Breakpoint condicional: pausar quando i === 5 e nome === "admin"
i === 5 && nome === "admin"

// Breakpoint condicional com operadores relacionais
contador > 100 || status === "erro"

// Breakpoint condicional verificando tipo
typeof usuario !== "undefined" && usuario.ativo === true

Limitações comuns:
- Expressões complexas degradam o desempenho, especialmente em loops com milhões de iterações.
- Condições que acessam propriedades de objetos undefined podem lançar exceções.
- Em linguagens compiladas, algumas expressões podem não ser avaliadas no contexto do debugger.

2. Estratégias Avançadas para Condições Eficientes

Para maximizar a eficiência, utilize contadores e flags como condições baseadas em estado:

// Usando contador para pausar a cada 100 iterações
contador % 100 === 0

// Flag de estado para pausar apenas após mudança específica
estadoAnterior !== estadoAtual && estadoAtual === "processando"

// Combinando múltiplas condições com operadores lógicos
(usuario.tentativas >= 3 || usuario.bloqueado) && usuario.tipo === "admin"

Evitando armadilhas comuns:

// PROBLEMA: variável não inicializada
i === undefined  // Nunca será verdade se i estiver definida

// SOLUÇÃO: verificar existência antes
typeof i !== "undefined" && i > 100

// PROBLEMA: escopo incorreto
// Condição que acessa variável fora do escopo atual
this.nome  // Pode falhar se this não for o esperado

// SOLUÇÃO: usar variáveis locais ou parâmetros
nomeParametro === "admin"

3. Logpoints: Depuração sem Interrupção

Logpoints são uma revolução na depuração. Eles permitem registrar mensagens no console sem interromper a execução, substituindo console.log temporário.

Configuração de mensagens personalizadas:

// Logpoint básico
"Valor de x é: {x}, y é: {y}"

// Logpoint com formatação e múltiplas variáveis
"Usuário {usuario.nome} - Tentativa {tentativa} de {maxTentativas}"

// Logpoint condicional com expressão
"Status alterado: {status} em {new Date().toISOString()}"

Vantagens em produção e ambientes de alta performance:
- Zero overhead quando desativados: debuggers modernos compilam logpoints apenas quando ativos.
- Não afetam a pilha de chamadas ou o estado da aplicação.
- Permitem depuração em servidores remotos sem modificar o código fonte.

4. Técnicas de Filtragem para Logpoints

Filtros avançados tornam os logpoints ainda mais poderosos:

// Filtro por tipo de exceção
"Erro capturado: {erro.message}"  // Apenas quando erro for capturado

// Filtro por nível de log
"[{severidade}] {mensagem}"  // Exibe apenas logs de severidade específica

// Uso de expressões regulares em mensagens
"Acesso ao recurso: {recurso.match(/^\/api/)}"  // Filtra apenas endpoints API

// Agrupamento por thread ou contexto
"[Thread {threadId}] Processando {dados.id}"

5. Integração com Debuggers Modernos

VS Code:

// Atalho: Clique direito na margem → "Add Conditional Breakpoint"
// Atalho para logpoint: Clique direito → "Add Logpoint"
// Sintaxe suportada: Expressões JavaScript/TypeScript completas

// Exemplo de condição no VS Code
this.state.count >= 5 && this.state.mode === "critical"

// Logpoint no VS Code
"Processando item {item.id} | Status: {item.status}"

Chrome DevTools:

// Breakpoint condicional: Clique direito na linha → "Add conditional breakpoint"
// Logpoint: Use "Logpoint" no menu de breakpoint condicional

// Condição no DevTools
window.debugMode && performance.now() > 5000

// Logpoint no DevTools
"[{performance.now().toFixed(2)}ms] Evento: {event.type}"

Diferenças entre IDEs:

IDE Sintaxe de Condição Suporte a Logpoint Atalho Principal
VS Code JavaScript/TypeScript Sim (nativo) F9 + clique direito
IntelliJ IDEA Java/Kotlin expressions Sim (via plugin) Ctrl+F8 + Alt+clique
Neovim (DAP) Linguagem do debugger Sim (via nvim-dap) :lua require'dap'.set_breakpoint()

6. Boas Práticas para Manutenção e Performance

Removendo breakpoints temporários:

// VS Code: Ctrl+Shift+F8 para remover todos os breakpoints
// Chrome DevTools: "Deactivate breakpoints" (ícone de pausa)
// IntelliJ: "View Breakpoints" (Ctrl+Shift+F8) → "Remove All"

// Versionamento de configurações de debug (launch.json)
{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "node",
            "request": "launch",
            "name": "Debug com breakpoints",
            "program": "${workspaceFolder}/app.js",
            "skipFiles": ["<node_internals>/**"]
        }
    ]
}

Impacto no desempenho:
- Evite condições complexas em loops com mais de 10.000 iterações.
- Prefira condições simples como i % 1000 === 0 em vez de expressões com chamadas de função.
- Desative logpoints após a depuração para evitar acúmulo de logs.

7. Casos de Uso Reais e Solução de Problemas

Depurando loops com milhares de iterações:

// Problema: Loop de 50.000 iterações com erro intermitente
for (let i = 0; i < 50000; i++) {
    // Breakpoint condicional: pausar apenas quando i for múltiplo de 1000
    i % 1000 === 0

    // Logpoint: registrar progresso sem pausar
    "Processando item {i} de 50000 | Status: {dados[i].status}"
}

Rastreando alterações de estado em tempo real:

// Logpoint para monitorar mudanças de estado
"Estado alterado: {estadoAnterior} → {estadoAtual} | Timestamp: {Date.now()}"

// Breakpoint condicional para pausar em transições específicas
estadoAnterior === "loading" && estadoAtual === "error"

Debugando condições assíncronas e promises:

// Logpoint em callback de Promise
"Promise resolvida: {resultado} | Tempo: {performance.now() - inicio}ms"

// Breakpoint condicional em catch
erro.code === "NETWORK_ERROR" && tentativas >= 3

// Logpoint em async/await
"Aguardando resposta da API... | Request ID: {requestId}"
"[{new Date().toISOString()}] Dados recebidos: {JSON.stringify(dados).substring(0, 100)}"

Referências