sono - assert preço




Quando as afirmações devem permanecer no código de produção? (11)

Há uma discussion sobre moderação sobre se as asserções, que em C ++ existem apenas em compilações de depuração por padrão, devem ser mantidas no código de produção ou não.

Obviamente, cada projeto é único, então minha pergunta aqui não é tanto se as afirmações devem ser mantidas, mas em quais casos isso é recomendável / não é uma boa ideia.

Por asserção, quero dizer:

  • Uma verificação de tempo de execução que testa uma condição que, quando falsa, revela um erro no software.
  • Um mecanismo pelo qual o programa é interrompido (talvez após um trabalho de limpeza mínimo).

Eu não estou necessariamente falando sobre C ou C ++.

Minha opinião é que, se você é o programador, mas não possui os dados (que é o caso da maioria dos aplicativos de desktop comerciais), você deve mantê-los, porque uma falha de análise mostra um erro, e você não deve ir com um bug, com o risco de corromper os dados do usuário. Isso obriga você a testar fortemente antes de embarcar e torna os bugs mais visíveis, portanto, mais fáceis de detectar e corrigir.

Qual sua opinião / experiência?

Felicidades,

Carl

Veja a questão relacionada here

Respostas e Atualizações

Hey Graham,

Uma afirmação é erro, pura e simples e, portanto, deve ser tratada como um. Como um erro deve ser tratado no modo de liberação, você não precisa realmente de declarações.

É por isso que eu prefiro a palavra "bug" ao falar sobre asserções. Isso torna as coisas muito mais claras. Para mim, a palavra "erro" é muito vaga. Um arquivo ausente é um erro, não um bug, e o programa deve lidar com isso. Tentar desreferenciar um ponteiro nulo é um erro, e o programa deve reconhecer que algo cheira a queijo ruim.

Portanto, você deve testar o ponteiro com uma declaração, mas a presença do arquivo com código de tratamento de erros normal.

Ligeiramente off-topic, mas um ponto importante na discussão.

Como um heads-up, se suas asserções entrarem no depurador quando elas falharem, por que não? Mas existem muitas razões para um arquivo não existir completamente fora do controle do seu código: direitos de leitura / gravação, disco cheio, dispositivo USB desconectado, etc. Já que você não tem controle sobre ele, eu sinto que as afirmações são não é o jeito certo de lidar com isso.

Carl

Thomas,

Sim, tenho o Código Completo e devo dizer que discordo totalmente desse conselho específico.

Digamos que o alocador de memória personalizado fique emperrado e zere um fragmento de memória que ainda é usado por algum outro objeto. Eu acontece de zerar um ponteiro que este objeto desreferencia regularmente, e uma das invariantes é que este ponteiro nunca é nulo, e você tem algumas asserções para ter certeza de que ele permaneça assim. O que você faz se o ponteiro de repente for nulo. Você apenas se () em torno dele, esperando que isso funcione?

Lembre-se, estamos falando sobre o código do produto aqui, então não há como invadir o depurador e inspecionar o estado local. Este é um bug real na máquina do usuário.

Carl


A menos que a criação de perfil mostre que as afirmações estão causando problemas de desempenho, digo que elas também devem permanecer na versão de produção.

No entanto, acho que isso também exige que você lide com falhas de asserção de maneira graciosa. Por exemplo, eles devem resultar em um tipo geral de diálogo com a opção de (automaticamente) relatar o problema para os desenvolvedores, e não apenas sair ou travar o programa. Além disso, você deve ter cuidado para não usar afirmações para condições que você realmente permite, mas possivelmente não goste ou considere indesejadas. Essas condições devem ser tratadas por outras partes do código.


ASSERÇÕES não são erros e não devem ser tratadas como erros. Quando uma afirmação é lançada, isso significa que há um bug no seu código ou, alternativamente, no código que chama seu código.

Existem alguns pontos para evitar a ativação de asserções no código de produção: 1. Você não quer que seu usuário final veja uma mensagem como "ASSERTION failed MyPrivateClass.cpp line 147. O usuário final NÃO é seu engenheiro de QA. 2. ASSERTION pode influenciar o desempenho

No entanto, há uma forte razão para deixar as asserções: ASSERTION pode influenciar o desempenho e o timing, e infelizmente isso às vezes é importante (especialmente em sistemas embarcados).

Eu tenho a tendência de votar em deixar a declaração no código de produção, mas certificando-me de que essas impressões de asserções não sejam expostas ao usuário final.

~ Yitzik


As asserções nunca devem permanecer no código de produção. Se uma afirmação específica parece ser útil no código de produção, então não deve ser uma afirmação; deve ser uma verificação de erro de tempo de execução, ou seja, algo codificado como este: if( condition != expected ) throw exception .

O termo "afirmação" passou a significar "uma verificação em tempo de desenvolvimento que não será executada em campo".

Se você começar a pensar que as afirmações podem chegar ao campo, inevitavelmente você também começará a fazer outros pensamentos perigosos, como imaginar se uma determinada afirmação realmente vale a pena ser feita. Não há nenhuma afirmação que não vale a pena ser feita. Você nunca deveria estar se perguntando "devo afirmar isso ou não?" Você só deveria estar se perguntando "Existe alguma coisa que eu esqueci de afirmar?"


Deixe as asserções ativadas no código de produção, a menos que você tenha medido que o programa é executado significativamente mais rápido com elas desativadas.

se não vale a pena medir para provar que é mais eficiente, então não vale a pena sacrificar a clareza por uma aposta de desempenho. "- Steve McConnell 1993

http://c2.com/cgi/wiki?ShipWithAssertionsOn


Eu acho melhor lidar com todos os erros que estão no escopo, e usar afirmações para suposições que estamos afirmando serem verdadeiras.

ou seja, se o seu programa está abrindo / lendo / fechando um arquivo, então não poder abrir o arquivo está no escopo - é uma possibilidade real, que seria negligente ignorar, em outras palavras. Então, isso deve ter código de verificação de erros associado a ele.

No entanto, digamos que seu fopen () seja documentado como sempre retornando um identificador válido de arquivo aberto. Você abre o arquivo e o passa para sua função readfile ().

Essa função readfile, neste contexto, e provavelmente de acordo com sua especificação de design, pode praticamente supor que obterá um arquivo ptr válido. Portanto, seria um desperdício adicionar um código de tratamento de erros para o caso negativo, em um programa tão simples. No entanto, deve pelo menos documentar a suposição, de alguma forma - garantir de alguma forma - que este é realmente o caso, antes de continuar sua execução. Não deve presumir que sempre será válido, caso seja chamado incorretamente, ou seja, copiado / colado em algum outro programa, por exemplo.

Então, readfile () {assert (fptr! = NULL); ..} é apropriado neste caso, enquanto o tratamento de erro completo não é (ignorando o fato de que, na verdade, a leitura do arquivo exigiria algum sistema de tratamento de erros).

E sim, essas afirmações devem permanecer no código de produção, a menos que seja absolutamente necessário desativá-las. Mesmo assim, você provavelmente deve desabilitá-las apenas em seções críticas de desempenho.


Eu raramente uso asserções para qualquer outra coisa que compila a verificação do tipo de tempo. Eu usaria uma exceção em vez de uma afirmação só porque a maioria dos idiomas são criados para lidar com eles.

Eu ofereço um exemplo

file = create-some-file();
_throwExceptionIf( file.exists() == false, "FILE DOES NOT EXIST");

contra

file = create-some-file();
ASSERT(file.exists());

Como o aplicativo lidaria com a afirmação? Eu prefiro o antigo método try catch de lidar com erros fatais.


Na maioria das vezes, quando eu uso asserção em java (a palavra-chave assert), eu automaticamente adiciono alguns códigos de produção depois. De acordo com o caso, pode ser uma mensagem de registro, uma exceção ... ou nada.

De acordo comigo, todas as suas afirmações são críticas no lançamento do desenvolvedor, não na produção. Alguns deles devem ser mantidos, outros devem ser descartados.


No meu C ++ eu defino REQUIRE (x), que é como assert (x), exceto que ele lança uma exceção se a afirmação falhar em uma compilação de lançamento.

Uma vez que uma afirmação falhada indica um erro, ela deve ser tratada seriamente, mesmo em uma compilação Release. Quando o desempenho do meu código é importante, geralmente utilizarei REQUIRE () para código de nível superior e assert () para código de nível inferior que deve ser executado rapidamente. Eu também uso REQUIRE em vez de afirmar se a condição de falha pode ser causada por dados passados ​​do código escrito por terceiros, ou por corrupção de arquivo (idealmente eu iria projetar o código especificamente para ser bem comportado em caso de corrupção de arquivo, mas nós nem sempre tem tempo para fazer isso.

Eles dizem que você não deve mostrar essas mensagens para os usuários finais, porque eles não vão entendê-los. Assim? Os usuários finais podem enviar um e-mail com uma captura de tela ou algum texto da mensagem de erro, o que ajuda a depurar. Se o usuário simplesmente disser "ele caiu", você terá menos capacidade de corrigi-lo. Seria melhor enviar as mensagens de falha de asserção para você mesmo automaticamente pela Internet, mas isso só funciona se o usuário tiver acesso à Internet e você puder obter sua permissão.


Permita-me citar o Código Completo de Steve McConnell. A seção sobre Asserções é 8.2.

Normalmente, você não quer que os usuários vejam mensagens de asserção no código de produção; As asserções são principalmente para uso durante o desenvolvimento e manutenção. As asserções são normalmente compiladas no código no momento do desenvolvimento e compiladas fora do código para produção.

No entanto, mais tarde na mesma seção, este conselho é dado:

Para um código altamente robusto, declare e manipule o erro de qualquer maneira.

Eu acho que, desde que o desempenho não seja um problema, deixe a asserção, mas em vez de exibir uma mensagem, grave-a em um arquivo de log. Eu acho que esse conselho também está no Code Complete, mas eu não estou achando isso agora.


Se você está pensando em deixar as afirmações em produção, você provavelmente está pensando sobre elas de forma errada. O ponto principal das asserções é que você pode desativá-las na produção, porque elas não fazem parte da sua solução. Eles são uma ferramenta de desenvolvimento, usada para verificar se suas suposições estão corretas. Mas o tempo que você entra em produção, você já deve ter confiança em suas suposições.

Dito isso, há um caso em que vou ativar as afirmações em produção: se encontrarmos um bug reproduzível na produção que estamos tendo dificuldade em reproduzir em um ambiente de teste, pode ser útil reproduzir o bug com as asserções ativadas. na produção, para ver se eles fornecem informações úteis.

Uma questão mais interessante é a seguinte: na sua fase de testes, quando você desativa as asserções?


Uma afirmação é erro, pura e simples e, portanto, deve ser tratada como um.

Como um erro deve ser tratado no modo de liberação, você não precisa realmente de declarações.

A principal vantagem que vejo para as asserções é uma quebra condicional - elas são muito mais fáceis de configurar do que perfurar pelas janelas do VC para configurar algo que leve 1 linha de código.