Pergunta

Os criadores de linguagem Go gravação :

Go não fornece afirmações. Eles são inegavelmente conveniente, mas a nossa experiência tem sido que os programadores usá-los como uma muleta para evitar pensar sobre manipulação de erro adequada e relatórios. tratamento de erros meios apropriados que os servidores continuam operação após erros não fatais, em vez de cair. meios de relatório de erros próprios que erros são direta e direto ao ponto, poupando o programador de interpretar um grande traço acidente. Erros precisos são particularmente importantes quando o programador ver os erros não está familiarizado com o código.

Qual é a sua opinião sobre isso?

Foi útil?

Solução

Não, não há nada de errado com assert contanto que você usá-lo como pretendido.

Ou seja, ele é suposto ser para a captura de casos que "não pode acontecer", durante a depuração, em oposição a manipulação de erro normal.

  • Assert:. Uma falha na lógica do próprio programa
  • Tratamento de erros:. Uma entrada ou sistema estado de erro não devido a um bug no programa

Outras dicas

Não, nem goto nem assert são maus. Mas ambos podem ser mal utilizado.

Assert é para checagens. Coisas que deveriam matar o programa, se eles não estão corretos. Não para validação ou como um substituto para o tratamento de erros.

Por essa lógica, breakpoints são maus também.

Afirma deve ser usado como uma ajuda de depuração, e nada mais. "Mal" é quando você tentar usá-los em vez de tratamento de erros.

Afirma estão lá para ajudá-lo, o programador, detectar e problemas correção que não deve existir e verificar se seus pressupostos permanecer fiel.

Eles não têm nada a ver com manipulação de erro, mas, infelizmente, alguns programadores abusar deles como tal, e depois declará-los "mal".

Eu gosto de usar assert muito. Acho que é muito útil quando estou a construir aplicações para o primeiro tempo (talvez para um novo domínio). Em vez de fazer muito verificação de erros de fantasia (que eu considero prematuro optimization) código I rápido e eu adicionar um monte de afirma. Depois de eu saber mais sobre como as coisas funcionam eu faço uma reescrita e remover alguns dos afirma e alterá-las para melhor tratamento de erros.

Por causa afirma que gastar muito menos tempo de codificação / depuração de programas.

Eu também tenho notado que o afirma ajuda-me pensar em muitas coisas que poderiam quebrar meus programas.

Eles devem ser usados ??para a detecção de erros no programa. Não entrada do usuário ruim.

Se usado corretamente, eles são não mal.

Como uma informação adicional, go fornece um built-in função panic. Isto pode ser usado no lugar de assert. Por exemplo.

if x < 0 {
    panic("x is less than 0");
}

panic irá imprimir o rastreamento de pilha, por isso, de alguma forma ele tem o propósito de assert.

Isto vem-se muito, e eu acho que um problema que faz com que as defesas de afirmações confusas é que eles são muitas vezes baseadas em verificação de argumento. Portanto, considere este exemplo diferente de quando você pode usar uma afirmação:

build-sorted-list-from-user-input(input)

    throw-exception-if-bad-input(input)

    ...

    //build list using algorithm that you expect to give a sorted list

    ...

    assert(is-sorted(list))

end

Você pode usar uma exceção para a entrada porque você esperar que você vai obter a entrada ruim às vezes. Você afirma que a lista é ordenada para ajudar a encontrar um bug em seu algoritmo, que, por definição, você não espera. A afirmação está na compilação de depuração somente, por isso mesmo que o cheque é caro, você não se importa fazê-lo em cada invocação da rotina.

Você ainda tem que unidade-teste o seu código de produção, mas isso é, uma maneira diferente, e complementar de ter certeza que seu código está correto. Os testes de unidade certificar-se de sua rotina faz jus ao seu interface, enquanto afirmações são uma forma de grão mais fino para se certificar de sua implementação está fazendo exatamente o que você espera que ele.

As afirmações não são maus, mas eles podem ser facilmente utilizadas. Eu concordo com a afirmação de que "as afirmações são frequentemente utilizados como uma muleta para evitar pensar sobre manipulação de erro adequada e relatórios". Eu já vi isso muitas vezes.

Pessoalmente, eu gosto de afirmações usar, porque eles documentar premissas que eu poderia ter feito enquanto escrever o meu código. Se estas suposições são quebradas, mantendo o código, o problema pode ser detectado durante o teste. No entanto, eu fazer o ponto de descascar para fora cada assert do meu código ao fazer uma compilação de produção (ou seja, usando #ifdefs). Retirando as afirmações na compilação de produção, eu eliminar o risco de qualquer mau uso deles como uma muleta.

Há também um outro problema com afirmações. Afirmações são verificadas apenas em tempo de execução. Mas é frequentemente o caso que o cheque que você gostaria de realizar poderia ter sido realizado em tempo de compilação. É preferível para detectar um problema em tempo de compilação. Para programadores C ++, boost fornece BOOST_STATIC_ASSERT que lhe permite fazer isso. Para programadores C, este artigo ( link de texto ) descreve uma técnica que pode ser usada para executar asserções em tempo de compilação.

Em resumo, a regra de ouro que eu sigo é: não use afirmações em uma compilação de produção e, se possível, use somente afirmações para as coisas que não podem ser verificados em tempo de compilação (ou seja, deve ser verificado em tempo de execução ).

Eu admito ter usado afirma embora não considerando o relatório de erro adequada. No entanto, isso não tira que eles são muito úteis quando usados ??corretamente.

Eles são especialmente úteis para se você quiser seguir o princípio "Bater precoce". Por exemplo, suponha que você está implementando um mecanismo de contagem de referência. Em certos locais no seu código você sabe que o refcount deve ser zero ou um. E também supor que, se o refcount é errado o programa não irá falhar imediatamente, mas durante o próximo ciclo de mensagens em que ponto ele vai ser difícil de descobrir por que as coisas deram errado. Uma declaração teria sido útil na detecção do erro mais perto de sua origem.

Eu prefiro evitar código que faz coisas diferentes na depuração e liberação.

quebra no depurador em uma condição e ter todas as informações de arquivo / linha é apesar de útil, também a expressão exata e o valor exato.

Ter uma declaração de que iria "avaliar a condição apenas em debug" pode ser uma otimização de desempenho e, como tal, útil apenas em 0,0001% dos programas - onde as pessoas sabem o que estão fazendo. Em todos os outros casos, isso é prejudicial, como a expressão pode realmente alterar o estado do programa:

assert(2 == ShroedingersCat.GetNumEars()); faria o programa fazer coisas diferentes na depuração e liberação.

Temos desenvolvido um conjunto de macros do assert que lançar uma exceção, e fazê-lo em ambos os versão de depuração e liberação. Por exemplo, THROW_UNLESS_EQ(a, 20); iria lançar uma exceção com o que () mensagem que tem tanto arquivo, linha e os valores reais de um, e assim por diante. Apenas uma macro teria o poder para isso. O depurador pode ser configurado para quebrar a 'atirar' do tipo excepção específica.

Eu não gosto afirma intensamente. Eu não iria tão longe como dizer que eles são maus embora.

Basicamente uma declaração vai fazer a mesma coisa que uma exceção não verificada seria, a única exceção é que o assert (normalmente) não devem ser mantidos para o produto final.

Se você construir uma rede de segurança para si mesmo durante a depuração e construção do sistema por que você iria negar essa rede de segurança para o seu cliente, ou o seu suporte de help desk, ou qualquer um que vai começar a usar o software que você está actualmente a construir. Use exceções exclusivamente para ambos afirma e situações excepcionais. Ao criar uma hierarquia de exceção apropriado você será capaz de discernir muito rapidamente um do outro. Só que desta vez os restos do assert no lugar e pode fornecer informações valiosas em caso de falha que de outra forma seriam perdidos.

Então, eu entendo totalmente os criadores de Go removendo afirma completamente e forçando os programadores a usar exceções para lidar com a situação. Há uma explicação simples para isso, exceção são apenas um melhor mecanismo para o trabalho porque vara com o arcaico afirma?

Resposta curta: Não, eu acredito afirmações pode ser útil

Eu comecei recentemente a adição de alguns afirma ao meu código, e é assim que eu venho fazendo isso:

Eu mentalmente dividir meu código em código limite e código interno. código de fronteira é o código que de entrada alças usuário, lê arquivos, e recebe dados da rede. Neste código, eu solicitar a entrada em um loop que só sai quando a entrada é válida (no caso de entrada do usuário interativo), ou lançar exceções no caso de irrecuperável arquivo / rede de dados corrupto.

código interno é tudo o resto. Por exemplo, uma função que define uma variável na minha classe pode ser definida como

void Class::f (int value) {
    assert (value < end);
    member = value;
}

e uma função que recebe entrada de uma rede pode ler como tal:

void Class::g (InMessage & msg) {
    int const value = msg.read_int();
    if (value >= end)
        throw InvalidServerData();
    f (value);
}

Isso me dá duas camadas de cheques. Qualquer coisa onde os dados é determinada pelo tempo de execução sempre recebe uma exceção ou manipulação de erro imediata. No entanto, o cheque extra no Class::f com os meios de instrução assert que se algum código interno já chama Class::f, eu ainda tenho uma verificação de sanidade. Meu código interno pode não passar um argumento válido (porque eu posso ter calculado value de alguma complexa série de funções), então eu como ter a afirmação na função de configuração para documentos que, independentemente de quem está chamando a função, value não deve ser maior ou igual a end.

Este parece se encaixar no que eu estou lendo em alguns lugares, que as afirmações deve ser impossível violar em um programa que funcione bem, enquanto excepções devem ser para casos excepcionais e errôneas que ainda são possíveis. Porque, em teoria estou validar todas as entradas, não deve ser possível para minha afirmação para ser disparado. Se for, o meu programa está errado.

assert é muito útil e você pode salvar um monte de retrocesso quando erros inesperados ocorrem por travar o programa nos primeiros sinais de problemas.

Por outro lado, é muito fácil de assert abuso.

int quotient(int a, int b){
    assert(b != 0);
    return a / b;
}

A versão adequada, correta seria algo como:

bool quotient(int a, int b, int &result){
    if(b == 0)
        return false;

    result = a / b;
    return true;
}

Então ... no longo prazo ... na grande figura ... Concordo que assert pode ser abusado. Eu faço isso o tempo todo.

assert está sendo abusada para o tratamento de erros, porque é menos digitação.

Assim como designers de linguagem, eles devem sim ver que o tratamento de erros apropriado pode ser feito com ainda menor digitação. Excluindo assert porque o seu mecanismo de exceção é detalhado não é a solução. Oh, espere, não vá não tem exceções tanto. Pena:)

Eu senti como chutar o autor na cabeça quando vi isso.

Eu uso afirma o tempo todo em código e, eventualmente, substituí-los todos quando eu escrever mais código. Eu usá-los quando eu não tenho escrito a lógica necessária e deseja ser alertado quando eu me deparo com o código em vez de escrever uma exceção que será eliminada como o projeto se aproxima de conclusão.

Exceções também misturar-se com o código de produção mais facilmente que eu não gosto. Um assert é mais fácil perceber que throw new Exception("Some generic msg or 'pretend i am an assert'");

O meu problema com essas respostas defender assert é ninguém especifica claramente o que o torna diferente de um regular erro fatal , e por uma declaração não pode ser um subconjunto de um exceção . Agora, com este dito, o que se a exceção nunca é pego? Será que o tornam uma afirmação de nomenclatura? E, por que você nunca querem impor uma restrição no idioma que uma exceção pode ser levantado que / nada / pode lidar?

Sim, afirma são maus.

Muitas vezes eles são utilizados em locais onde o tratamento de erros apropriado deve ser usado. Acostume-se a escrever o tratamento de erros adequada qualidade de produção desde o início!

Normalmente, eles ficam no caminho de escrever testes de unidade (a menos que você escrever um personalizado afirmar que interage com o seu equipamento de teste). Isso é muitas vezes porque eles são usados ??onde a manipulação de erro adequado deve ser usado.

Na maior parte eles são compilados fora da versão cria o que significa que nenhum dos seus "testes" está disponível quando você está executando o código que você realmente liberar; dado que em situações multi-threaded os piores problemas, muitas vezes só aparecem no código de liberação isso pode ser ruim.

Às vezes, eles são uma muleta para projetos de outra forma quebrados; ou seja, o projeto do código permite que um usuário de chamá-lo de uma forma que ele não deve ser chamado e os assert "previne" este. Corrigir o design!

Eu escrevi mais sobre isso no meu blog em 2005 aqui: http://www.lenholgate.com/blog/2005/09/assert-is-evil.html

Se o afirma que está falando significa que os vômitos programa e então existe, afirmações podem ser muito ruim. Isso não quer dizer que eles são sempre a coisa errada a utilização, são uma construção que é muito facilmente mal utilizado. Eles também têm muitas alternativas melhores. Coisas como essa são bons candidatos para ser chamado de mal.

Por exemplo, um terceiro módulo do partido (ou qualquer módulo realmente) quase nunca deve sair do programa chamando. Isso não dá o programador chamar qualquer controle sobre o risco do programa devem ter naquele momento. Em muitos casos, os dados é tão importante que até mesmo salvar dados corrompido é melhor do que perder esses dados. Afirma pode forçá-lo a perder dados.

Algumas alternativas aos afirma:

  • Usando um depurador,
  • Console / banco de dados / other logging
  • Exceções
  • Outros tipos de tratamento de erros

Algumas referências:

Mesmo as pessoas que defendem assert acho que eles devem ser utilizados apenas em desenvolvimento e não na produção:

Esta pessoa diz que afirma deve ser usado quando o módulo tem potencialmente corrompido dados que persiste após uma exceção é lançada: http://www.advogato.org/article/949.html . Este é certamente um ponto razoável, no entanto, um módulo externo deve não prescrever o quão importante os dados corrompidos é o programa de chamada (por sair "para" eles). A maneira correta de lidar com isso é lançando uma exceção que deixa claro que o programa pode estar agora em um estado inconsistente. E uma vez que bons programas consistem principalmente em módulos (com um pouco de código cola no executável principal), afirma são quase sempre a coisa errada a fazer.

Não tanto o mal como geralmente contraproducente. Há uma separação entre a verificação de erros permanente e depuração. Assert faz as pessoas pensarem tudo depuração deve ser permanente e causa problemas de legibilidade maciças quando usado muito. manipulação de erro permanente deve ser melhor do que isso, quando necessário, e desde assert faz com seus próprios erros é uma prática questionável bonita.

i nunca use assert (), exemplos mostram geralmente algo como isto:

int* ptr = new int[10];
assert(ptr);

Isso é ruim, eu nunca fazer isso, o que se meu jogo está alocando um bando de monstros? Por que eu deveria travar o jogo, em vez disso você deve lidar com os erros graciosamente, então, fazer algo como:

CMonster* ptrMonsters = new CMonster[10];
if(ptrMonsters == NULL) // or u could just write if(!ptrMonsters)
{
    // we failed allocating monsters. log the error e.g. "Failed spawning 10 monsters".
}
else
{
    // initialize monsters.
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top