Há uma discussão em comp.lang.c ++. Moderada sobre se as asserções, que em C ++ existem apenas em construções de depuração por padrão, devem ser mantidas no código de produção ou não.
Obviamente, cada projeto é único, portanto, minha pergunta aqui não é tanto se as afirmações devem ser mantidas, mas , nesses casos, isso é recomendável / não é uma boa idéia.
Por afirmação, quero dizer:
- Uma verificação em tempo de execução que testa uma condição que, quando falsa, revela um bug no software.
- Um mecanismo pelo qual o programa é interrompido (talvez após um trabalho de limpeza realmente mínimo).
Eu não estou necessariamente falando sobre C ou C ++.
Minha opinião é que, se você é programador, mas não possui os dados (que é o caso da maioria dos aplicativos comerciais para desktop), você deve mantê-los, porque uma asserção falha mostra um erro e você não deve ir com um bug, com o risco de corromper os dados do usuário. Isso força você a testar fortemente antes de enviar, e torna os bugs mais visíveis, facilitando assim a localização e a correção.
Qual a sua opinião / experiência?
Felicidades,
Carl
Veja a pergunta relacionada aqui
Respostas e atualizações
Hey Graham,
Uma afirmação é erro, pura e simples e, portanto, deve ser tratada como uma. Como um erro deve ser tratado no modo de liberação, você realmente não precisa de asserções.
É por isso que prefiro a palavra "bug" ao falar sobre afirmaçõ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 bug, e o programa deve reconhecer que algo cheira a queijo ruim.
Portanto, você deve testar o ponteiro com uma asserção, mas a presença do arquivo com o código de tratamento de erros normal.
Ligeiro fora do tópico, mas um ponto importante na discussão.
Como aviso, se suas afirmações entrarem no depurador quando falharem, por que não? Mas existem muitas razões pelas quais um arquivo não pode estar completamente fora do controle do seu código: direitos de leitura / gravação, disco cheio, dispositivo USB desconectado etc. etc. Como você não tem controle sobre isso, sinto que as afirmações são não é o caminho certo para lidar com isso.
Carl
Thomas,
Sim, tenho o Código Completo e devo dizer que discordo totalmente desse conselho em particular.
Digamos que seu alocador de memória personalizado estrague tudo e zere um pedaço de memória que ainda é usado por outro objeto. Por acaso zero um ponteiro que esse objeto desreferencia regularmente, e um dos invariantes é que esse ponteiro nunca é nulo, e você tem algumas afirmações para garantir que ele continue assim. O que você faz se o ponteiro de repente for nulo. Você apenas se () está em volta dele, esperando que funcione?
Lembre-se, estamos falando de código de produto aqui, portanto não há como entrar no depurador e inspecionar o estado local. Este é um bug real na máquina do usuário.
Carl
Respostas:
Asserções são comentários que não ficam desatualizados. Eles documentam quais estados teóricos são pretendidos e quais não devem ocorrer. Se o código for alterado para que os estados permitam a alteração, o desenvolvedor será informado em breve e precisará atualizar a asserção.
fonte
Permitam-me citar o código completo de Steve McConnell. A seção Asserções é 8.2.
No entanto, posteriormente na mesma seção, este conselho é dado:
Penso que, desde que o desempenho não seja um problema, deixe a afirmação inserida, mas, em vez de exibir uma mensagem, faça-a gravar em um arquivo de log. Acho que esse conselho também está no Código Completo, mas não o estou encontrando agora.
fonte
Deixe as afirmaçõ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.
http://c2.com/cgi/wiki?ShipWithAssertionsOn
fonte
assert ref != null;
é diferente deif (ref == null) throw new IllegalArgumentException();
Você não deve usar o primeiro para pré-condições que podem ser falsas. Você precisa usarassert
para coisas que não podem ser falsas. Exemplo,int i = -1 * someNumber; i = i * i;
mais tarde, para lembrar às pessoas quei
é positivo,assert i > 0;
Se você está pensando em deixar afirmações na produção, provavelmente está pensando errado. O ponto principal das afirmaçõ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 no momento em que você entra em produção, você já deve ter confiança em suas suposições.
Dito isso, há um caso em que ativarei asserções na produção: se encontrarmos um bug reproduzível na produção que estamos tendo dificuldades em reproduzir em um ambiente de teste, pode ser útil reproduzir o bug com as asserções ativadas em produção, para ver se eles fornecem informações úteis.
Uma pergunta mais interessante é a seguinte: na sua fase de teste, quando você desativa as afirmações?
fonte
As asserções nunca devem permanecer no código de produção. Se uma afirmação em particular parece útil no código de produção, não deve ser uma afirmação; deve ser uma verificação de erro tempo de execução, ou seja, algo codificado como este:
if( condition != expected ) throw exception
.O termo 'asserção' passou a significar "uma verificação apenas no tempo de desenvolvimento que não será executada em campo".
Se você começar a pensar que afirmações podem chegar ao campo, inevitavelmente também começará a fazer outros pensamentos perigosos, como se perguntar se vale a pena fazer alguma afirmação. Não há afirmação que não valha a pena fazer. Você nunca deve estar se perguntando "devo afirmar isso ou não?" Você só deve estar se perguntando "Existe algo que eu esqueci de afirmar?"
fonte
A menos que o perfil mostre que as asserções estão causando problemas de desempenho, eu digo que elas também devem permanecer no lançamento da produção.
No entanto, acho que isso também exige que você lide com as falhas de asserção de maneira um tanto graciosa. Por exemplo, eles devem resultar em um tipo geral de diálogo com a opção de (automaticamente) relatar o problema aos desenvolvedores e não apenas encerrar ou travar o programa. Além disso, você deve tomar cuidado para não usar asserções para condições que realmente permite, mas possivelmente não gosta ou considera indesejadas. Essas condições devem ser tratadas por outras partes do código.
fonte
No meu C ++, defino REQUIRE (x), que é como assert (x), exceto que lança uma exceção se a asserção falhar em uma versão.
Como uma afirmação com falha indica um bug, ela deve ser tratada com seriedade, mesmo em uma versão do 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. Também uso REQUIRE em vez de afirmar se a condição de falha pode ser causada por dados passados de código gravado por terceiros ou por corrupção de arquivo (idealmente, eu projetaria 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 de afirmação aos usuários finais, porque eles não as entenderão. 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 na depuração. Se o usuário simplesmente disser "travou", você terá menos capacidade de corrigi-lo. Seria melhor enviar automaticamente as mensagens de falha de afirmação pela Internet, mas isso só funciona se o usuário tiver acesso à Internet e você puder obter sua permissão.
fonte
Se você deseja mantê-los, substitua-os pelo tratamento de erros. Nada pior do que um programa simplesmente desaparecendo. Não vejo nada de errado em tratar certos erros como erros sérios, mas eles devem ser direcionados para uma seção do seu programa equipada para lidar com eles, coletando dados, registrando-os e informando ao usuário que seu aplicativo teve alguma condição indesejada e está saindo.
fonte
Desde que sejam tratados como qualquer outro erro, não vejo problema com ele. Lembre-se de que as afirmações com falha em C, como em outros idiomas, acabam de sair do programa e isso geralmente não é suficiente para os sistemas de produção.
Existem algumas exceções - o PHP, por exemplo, permite criar um manipulador personalizado para falhas de asserção, para que você possa exibir erros personalizados, fazer log detalhado, etc., em vez de apenas sair.
fonte
Nosso software de servidor de banco de dados contém asserções de produção e depuração. As asserções de depuração são exatamente isso - elas são removidas no código de produção. As asserções de produção só acontecem se (a) existir alguma condição que nunca deve existir e (b) não for possível recuperar com segurança essa condição. Uma asserção de produção indica que um erro no software foi encontrado ou ocorreu algum tipo de corrupção de dados.
Como este é um sistema de banco de dados e estamos armazenando dados potencialmente críticos para a empresa, fazemos o possível para evitar dados corrompidos. Se existir uma condição que possa nos levar a armazenar dados incorretos, nós imediatamente declaramos, revertemos todas as transações e paramos o servidor.
Dito isso, também tentamos evitar afirmações de produção em rotinas críticas ao desempenho.
fonte
Vejo afirmações como testes de unidade em linha. Útil para um teste rápido durante o desenvolvimento, mas, em última análise, essas afirmações devem ser refatoradas para serem testadas externamente em testes de unidade.
fonte
Acho melhor lidar com todos os erros que estão no escopo e usar asserções para suposições que afirmamos serem verdadeiras.
ou seja, se o seu programa estiver abrindo / lendo / fechando um arquivo, não será possível abrir o arquivo no escopo - é uma possibilidade real, que seria negligente ignorar, em outras palavras. Portanto, isso deve ter um código de verificação de erro associado a ele.
No entanto, digamos que seu fopen () esteja documentado como sempre retornando um identificador de arquivo aberto válido. Você abre o arquivo e o passa para a função readfile ().
Essa função readfile, neste contexto, e provavelmente de acordo com sua especificação de design, pode assumir que ele obterá um ptr de arquivo válido. Portanto, seria um desperdício adicionar 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 esse é realmente o caso, antes de continuar sua execução. Na realidade, não deve assumir que sempre será válido, caso seja chamado incorretamente ou seja copiado / colado em outro programa, por exemplo.
Então, readfile () {assert (fptr! = NULL); ..} é apropriado nesse caso, embora o tratamento completo de erros não seja (ignorando o fato de que realmente ler o 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 desativá-los apenas em seções críticas de desempenho.
fonte
Suponha que um pedaço de código esteja em produção e atinja uma afirmação que normalmente seria acionada. A afirmação encontrou um bug! Exceto que não, porque a afirmação está desativada.
Então o que acontece agora? Ou o programa irá (1) travar de maneira não informativa em um ponto mais afastado da origem do problema ou (2) executar alegremente até a conclusão, provavelmente dando o resultado errado.
Nenhum dos cenários é convidativo. Deixe as afirmações ativas, mesmo na produção.
fonte
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 asserção apenas porque a maioria dos idiomas é criada para lidar com eles.
Eu ofereço um exemplo
contra
Como o aplicativo lidaria com a afirmação? Prefiro o antigo
try catch
método de lidar com erros fatais.fonte
Na maioria das vezes, quando uso asserção em java (a palavra-chave assert), adiciono automaticamente alguns códigos de produção depois. De acordo com o caso, pode ser uma mensagem de log, uma exceção ... ou nada.
De acordo com mim, todas as suas afirmações são críticas no lançamento do desenvolvedor, e não na produção. Alguns deles devem ser mantidos, outros devem ser descartados.
fonte
As afirmações não são erros e não devem ser tratadas como erros. Quando uma asserção é lançada, isso significa que há um erro no seu código ou, alternativamente, no código que está chamando o seu código.
Existem alguns pontos para evitar a ativação de asserções no código de produção: 1. Você não deseja que o usuário final veja uma mensagem como "ASSERTION falhou MyPrivateClass.cpp linha 147. O usuário final NÃO é você engenheiro de QA. 2. A ASSERÇÃO pode influenciar o desempenho
No entanto, há um forte motivo para deixar afirmações: a afirmação pode influenciar o desempenho e o tempo, e infelizmente isso às vezes é importante (especialmente em sistemas embarcados).
Costumo votar em deixar a afirmação ativada 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
fonte
Uma afirmação é erro, pura e simples e, portanto, deve ser tratada como uma.
Como um erro deve ser tratado no modo de liberação, você realmente não precisa de asserções.
O principal benefício que vejo para as afirmações é uma quebra condicional - elas são muito mais fáceis de configurar do que vasculhar as janelas do VC para configurar algo que requer 1 linha de código.
fonte