O código de depuração deve ser deixado no local, sempre ou adicionado apenas durante a depuração e removido quando o bug foi encontrado?

35

Eu, por exemplo, apenas adiciono código de depuração (como instruções de impressão) quando estou tentando localizar um bug. E depois que o encontrei, removo o código de depuração (e adiciono um caso de teste que testa especificamente esse bug). Eu sinto que está atrapalhando o código real e, portanto, não tem lugar lá, a menos que eu esteja depurando.

Como você faz isso? Você deixa o código de depuração no lugar ou remove-o quando obsoleto (o que pode ser difícil de julgar quando é esse o caso)?

gablin
fonte

Respostas:

30

As instruções de impressão de depuração devem ser removidas; no entanto, se você precisar adicioná-los para depurar um problema de produção, talvez valha a pena considerar se você tem informações suficientes sendo colocadas em sua estrutura de log. Informações sobre parâmetros, condições de erro e assim por diante podem ser úteis mais tarde quando o próximo bug aparecer. O uso de uma boa estrutura de log que pode ter as mensagens de log de rastreamento ou depuração ativadas dinamicamente pode ser muito útil.

Alaric
fonte
5
+1 principalmente por mencionar a existência de uma estrutura de depuração sensata. Se isso estiver implementado inicialmente e houver vários níveis de depuração, esperamos que o código de produção possa ser executado sem chamar rotinas caras de depuração, e o código de desenvolvimento possa ser executado com qualquer nível de escrutínio necessário, logado da maneira que desejar.
Orbling
11
Concorde com Orbling. Além disso, para códigos de depuração que não sejam apenas a exibição de informações que tiveram impacto no desempenho ou outro motivo não adequado para produção. (por exemplo, uma declaração sobre o resultado da função, por exemplo, verificando o resultado de uma classificação), você pode considerar dois modos de criação de destino. modo de depuração e modo de liberação.
Zekta Chan
16

O código adicionado especificamente para depuração deve ser removido do software de produção.

A remoção completa ou a inserção em seções de compilação condicional (como em C / C ++ / C #) depende de você e do seu padrão de codificação.

Há várias razões para isso:

  1. Pode haver implicações de segurança se esse código for executado ou se alguém puder acessar sua saída.
  2. Isso pode tornar o aplicativo mais lento.
  3. Pode ser confuso para outros desenvolvedores olharem para o código (ou para você mesmo) seis meses depois.
ChrisF
fonte
+1 para compilação condicional, mas os blocos de comentários funcionarão em idiomas que não os suportam. Você nunca deve deixá-lo compilado em um release de produto, mas às vezes é excessivamente ineficiente continuar excluindo-o totalmente toda vez que você desejar descartar uma versão de lançamento.
Bill
11
Trabalhei em ambientes em que o código C / C ++ sempre foi compilado com opções de depuração, caso o código de produção precisasse ser depurado ou um coredump examinado. Às vezes, esse comando sempre pronto para depuração exigia que as instruções de depuração fossem deixadas para que pudessem ser ativadas com um sinalizador sem recompilar o código. O Java sempre permite a depuração se as opções da JVM estiverem configuradas para isso, portanto, é necessário um trabalho de preparação relativamente menor para depurar as coisas posteriormente.
Michael Shopsin
16

ChrisF e Alaric ambos têm pontos válidos; +1 para eles. Eu posso identificar pelo menos 5 tipos diferentes de código de depuração que eu uso.

  1. Usando logs para despejar o estado do sistema em um momento específico.

    void function(...)
    {
        ...dump everything i know about.
    }
    
  2. Usando logs para pontos de verificação de execução.

    void function(...)
    {
        ...got here 1
        ...got here 2
    }
    
  3. Código que realmente força uma determinada condição a ser verdadeira, mas quebra o comportamento normal. Exemplo:

    • Suponha que você tenha alguns registros relacionados a um erro, mas não pode reproduzir o problema. Você pode tentar escrever um código que force certas variáveis ​​a terem certos valores que correspondam às informações no log.
  4. Registro de verificação - eu classificaria isso como um registro detalhado que pode ser usado para validar a correção do software que não deve ser incluída na produção, como validar as etapas individuais de um algoritmo, por exemplo.

  5. Registro de operação - consulte a publicação de Alaric . Isso é basicamente o que quero dizer com "log de operações".

1, 2 e 3 devem ser retirados completamente. Algo como 4, eu provavelmente compilaria condicionalmente o código. Para 5, Alaric tinha um grande argumento sobre ser capaz de desativar dinamicamente os logs. Isso pode abordar o ponto de ChrisF em seu segundo marcador na maioria dos casos.

Pemdas
fonte
11
Este é um bom resumo. No entanto, seria melhor se você pudesse formatá-lo corretamente, substituindo 1)… por 1.… (para que a formatação do Markdown o pegue como uma lista) e indentando o código de exemplo por 8 espaços (novamente, para que o Markdown o pegue como exemplo) código dentro de uma lista).
Konrad Rudolph
@ Konrad Rudolph: Feito.
gablin
3

Depende do que o código está fazendo. Algum código usado para depuração pode ser deixado como está e alguns devem ser removidos.

O código que verifica a integridade dos parâmetros em um método nem sempre é útil quando o código está funcionando corretamente, mas geralmente é mantido para garantir que o código continue funcionando corretamente.

Às vezes, você escreve o código de maneira diferente para facilitar a depuração do código, por exemplo, calcular um valor e colocá-lo em uma variável local e, em seguida, usa a variável na próxima linha, o que facilita a verificação do resultado do cálculo ao avançar uma etapa. através do código. Você pode reescrever o código para usar diretamente o valor calculado, mas o custo do uso da variável local é tão pequeno (se houver) que há poucas razões para reescrever o código. Além disso, há um ponto em deixar o código inalterado depois de testá-lo; sempre há um pequeno risco de que você introduza um bug ao alterá-lo.

O código que você adiciona apenas para rastrear um bug específico geralmente pode ser removido depois que você o encontra.

Guffa
fonte
2

Era uma vez eu costumava usar muito código de depuração. Eu estava quase totalmente mirando no Windows, então havia uma grande quantidade dessa função de saída da string de depuração que não me lembro mais como escrever, para que eu pudesse capturar o rastreamento com um programa específico.

Algum código de depuração permaneceu no lugar, coisas específicas destinadas a dar o aninhamento de chamadas. No entanto, mesmo que a coisa da string de depuração não seja visível em um sistema de produção, tudo foi feito sob compilação condicional.

A realidade é, no entanto, que todo esse código de depuração foi um grande esforço para algo idealmente tratado de uma maneira diferente - usando, é claro, um depurador. Na época, eu não estava tão impressionado com o depurador Borland C ++. As ferramentas estavam lá, mas muitas vezes deram resultados enganosos, e o uso do depurador não IDE (geralmente necessário) significava memorizar as teclas de atalho, o que significava uma distração do trabalho em questão.

A única experiência de depuração que achei pior é o GDB da linha de comando.

Ser um especialista nas ferramentas que você usa todos os dias é, obviamente, importante - mas a depuração não deve ser algo que você faz todos os dias. Se você usa o depurador com tanta frequência, não há problema em aprender dezenas de comandos e / ou atalhos de teclado, isso me parece um sinal de alerta.

No momento em que eu estava trabalhando no Visual Studio 7, estava claro que a depuração poderia ser muito prática e eficaz. Se você pode fazer sua depuração no Visual Studio (edições expressas incluídas), a depuração é fácil. Sem dúvida, se você pode encontrar o front end GUI / IDE correto, o GDB também é fácil e eficaz, embora ainda não tenha feito essa pesquisa.

Há também algo a ser dito para o teste de unidade, com a análise de cobertura usando o gcov. Quanto mais confiante você estiver no comportamento de suas bibliotecas, menor será a profundidade de depuração - e menos frequentemente você precisará do depurador em primeiro lugar. E escrever testes de unidade é razoavelmente algo que você deve fazer na maioria dos dias.

Ferramenta inesperadamente importante = cmake, uma ferramenta de construção que me permite alternar facilmente entre criar para o GCC e para VC ++, entre outras coisas. Para que eu possa fazer meus testes de unidade e cobertura baseada em gcov usando o GCC, mas mude facilmente para o VC ++ para usar o depurador.

Steve314
fonte
Um depurador pode ser inútil, se não perigoso, em aplicativos multiencadeados, mas eu gosto do seu comentário de bandeira vermelha.
pemdas
@Pemdas - Eu ainda não tive um problema sério nesse sentido, embora o multi-threading obviamente não seja compatível com o depurador. Mesmo assim, acho que as ferramentas certas provavelmente são uma solução melhor do que o código de depuração em princípio. Uma ferramenta de análise estática que pode detectar condições de corrida, conflitos, condições em que dois threads podem enfrentar a mesma memória / recurso ao mesmo tempo e assim por diante seria bom. Não tenho idéia do que está disponível nesse sentido, embora eu saiba que existem algumas ferramentas inteligentes por aí. klee, por exemplo - eu não entendo, mas a descrição básica parece muito impressionante.
precisa saber é o seguinte
"Eu acho que as ferramentas certas provavelmente são uma solução melhor do que o código de depuração em princípio" Essa é uma declaração perigosa;). Ter ferramentas que pré-executem parte da análise pode ser bom, mas eu me preocupo que os desenvolvedores, especialmente os novos, começem a ficar muito dependentes das ferramentas, como alguém que precisa usar uma calculadora para descobrir o que são 15% de 100.
pemdas
Ficar muito dependente de ferramentas que ainda nem pesquisei parece improvável. No exemplo da sua calculadora, sim, mas ainda usarei o OpenOffice Calc em vez de escrever minha própria planilha simples. Há um tempo para o código de depuração (mesmo com um depurador - por exemplo, seu próprio caso de criação de condição bizarra), mas se for além de um certo ponto, as ferramentas existentes vencem. E quando se trata de subtrair 15% de 115, também usarei essa calculadora - o que muitas pessoas dariam como resposta óbvia (100) está errada. No multithreading, respostas obviamente corretas são infames por, às vezes, se mostrarem erradas.
precisa saber é o seguinte
1

Minha opinião: código de depuração usado para matar um bug no código em questão, geralmente removo completamente. Código de depuração usado para matar um bug resultante de forças externas. Geralmente, eu simplesmente comento.

Loren Pechtel
fonte
-1

Se o bug for do teste de unidade ou do interno, o código de depuração poderá ser completamente removido. Mas se o bug é da produção, é melhor o código de depuração estar lá dentro das tags de compilação. Colocá-lo dentro de tags de compilação ajudará os outros desenvolvedores a entender que esse código é apenas para fins de depuração.

Manoj R
fonte
-1

Use TDD , para que seu código de teste sempre tenha um local onde seja mantido.

dukeofgaming
fonte
Como isso responde à pergunta?
Gnat
Porque o TDD leva você a "depurar" ou código de teste que você não precisa remover.
Dukeofgaming
Eu não sigo desculpe. Como é isso?
mosquito