Um colega de trabalho adicionou o comando assert algumas vezes em nossas bibliotecas em locais onde eu teria usado uma instrução if e lançado uma exceção. (Eu nunca tinha ouvido falar de assert antes disso.) Aqui está um exemplo de como ele o usou:
assert('isset($this->records); /* Records must be set before this is called. */');
Eu teria feito:
if (!isset($this->records)) {
throw new Exception('Records must be set before this is called');
}
Ao ler a documentação do PHP sobre assert , parece que é recomendado que você certifique-se de que assert esteja ativo e adicione um manipulador antes de usar assert. Não consigo encontrar um lugar onde ele tenha feito isso.
Então, minha pergunta é, usar assert é uma boa ideia dada a situação acima e devo usá-lo com mais frequência em vez de exceções if e?
Outra observação, estamos planejando usar essas bibliotecas em uma variedade de projetos e servidores, incluindo projetos dos quais podemos nem mesmo fazer parte (as bibliotecas são de código aberto). Isso faz alguma diferença no uso de assert?
'isset
(a linha de código comassert
)? Não apenasisset
(sem as aspas simples'
)?Respostas:
A regra prática aplicável na maioria das línguas (tudo que eu sei vagamente) é que an
assert
é usado para afirmar que uma condição é sempre verdadeira, enquanto anif
é apropriado se for concebível que às vezes falhe.Nesse caso, eu diria que
assert
é apropriado (com base em meu fraco entendimento da situação) porque semprerecords
deve ser definido antes de o método fornecido ser chamado. Portanto, uma falha em definir o registro seria um bug no programa, e não uma condição de tempo de execução. Aqui, o está ajudando a garantir (com testes adequados) que não há um caminho de execução de programa possível que possa fazer com que o código que está sendo protegido com o seja chamado sem ter sido definido.assert
assert
records
A vantagem de usar
assert
em oposição aif
é queassert
geralmente pode ser desativado no código de produção, reduzindo assim a sobrecarga. O tipo de situação que é mais bem tratadaif
poderia ocorrer durante o tempo de execução no sistema de produção e, portanto, nada é perdido por não ser capaz de desligá-los.fonte
assert_options(ASSERT_BAIL)
. É mais rápido do que as soluções manuais if / throw de qualquer maneira.Pense em afirmações como "comentários poderosos". Em vez de um comentário como:
// Note to developers: the parameter "a" should always be a number!!!
usar:
assert('is_numeric(a) /* The parameter "a" should always be a number. */');
Os significados são exatamente os mesmos e destinam-se ao mesmo público, mas o primeiro comentário é facilmente esquecido ou ignorado (não importa quantos pontos de exclamação), enquanto o "comentário poderoso" não está disponível apenas para humanos lerem e entenderem, ele também é constantemente testado por máquina durante o desenvolvimento e não será ignorado se você configurar um bom manuseio de assert no código e nos hábitos de trabalho.
Visto dessa forma, afirmações são um conceito completamente diferente de if (erro) ... e exceções, e podem coexistir.
Sim, você deve comentar seu código e, sim, você deve usar "comentários poderosos" (afirmações) sempre que possível.
fonte
Depende totalmente da sua estratégia de desenvolvimento. A maioria dos desenvolvedores desconhece
assert()
e usa o teste de unidade downstream. Mas esquemas de teste proativos e integrados às vezes podem ser vantajosos.assert é útil, porque pode ser habilitado e desabilitado. Ele não drena o desempenho se nenhum manipulador de asserção for definido. Seu colega não tem um, e você deve criar algum código que o habilite temporariamente no ambiente de desenvolvimento (se E_NOTICE / E_WARNINGs estiverem ativados, então deve estar o manipulador de asserção). Eu o uso ocasionalmente onde meu código não tolera tipos de variáveis misturados - eu normalmente não me envolvo na digitação estrita em um PHP de digitação fraca, mas há casos de uso aleatórios:
function xyz($a, $b) { assert(is_string($a)); assert(is_array($b));
O que, por exemplo, compensaria a falta de especificadores de tipo
string $a, array $b
. PHP5.4 irá suportá-los, mas não verificará.fonte
Assert não é um substituto para o controle de fluxo normal, como
if
ou exceções, porque se destina apenas a ser usado para depuração durante o desenvolvimento.fonte
Uma nota importante sobre assert no PHP anterior a 7. Diferente de outras linguagens com uma construção assert, o PHP não joga declarações assert completamente - ele o trata como uma função (faça um debug_backtrace () em uma função chamada por um assertion). Desligar assert parece apenas fazer a função hotwire em não fazer nada no motor. Note que o PHP 7 pode ser feito para emular este comportamento definindo zend.assertions para 0 ao invés dos valores mais normais de 1 (ligado) ou -1 (desligado).
O problema surge em que assert aceitará qualquer argumento - mas se o argumento não for uma string, então assert obtém os resultados da expressão se assert estiver ativado ou desativado. Você pode verificar isso com o seguinte bloco de código.
<?php function foo($a) { echo $a . "\n"; return TRUE; } assert_options(ASSERT_ACTIVE, FALSE); assert( foo('You will see me.')); assert('foo(\'You will not see me.\')'); assert_options(ASSERT_ACTIVE, TRUE); assert( foo('Now you will see')); assert('foo(\'both of us.\')');
Dada a intenção de assert, este é um bug, e um bug antigo desde que está na linguagem desde que assert foi introduzido no PHP 4.
As strings passadas para assert são avaliadas, com todas as implicações de desempenho e riscos que vêm com isso, mas é a única maneira de fazer as declarações assert funcionarem da maneira que deveriam no PHP (este comportamento foi descontinuado no PHP 7.2).
EDIT: Alterado acima para observar as alterações no PHP 7 e 7.2
fonte
zend.assertions
configuração inicial para desligar completamenteassert()
.Assert só deve ser usado no desenvolvimento, pois é útil para depuração. Portanto, se você quiser, pode usá-los para desenvolver seu site, mas deve usar exceções para um site ativo.
fonte
Não, seu colega de trabalho não deve usá-lo como um manipulador de erros de propósito geral. De acordo com o manual:
Se você estiver familiarizado com conjuntos de testes automatizados, o verbo "assert" geralmente é usado para verificar a saída de algum método ou função. Por exemplo:
function add($a, $b) { return $a + $b; } assert(add(2,2) == 5, 'Two and two is four, dummy!'); assert(is_numeric(add(2,2)), 'Output of this function to only return numeric values.');
Seu colega de trabalho não deve usá-lo como um manipulador de erros de propósito geral e, neste caso, como uma verificação de entrada. Parece que é possível que o campo de registros não seja definido por algum usuário de sua biblioteca.
fonte
Seu colega de trabalho está realmente tentando aplicar design by contract (DbC) da linguagem Eiffel e baseado no livro: Object Oriented Software Construction, 2nd Edition.
A afirmação, como ele a usou, seria a parte {P} da lógica de Hoare ou triplo de Hoare: {P} C {Q}, onde {P} é a afirmação de pré-condição (íons) e {Q} são a afirmação (íon) de pós-condição.
Eu tomaria nota crítica dos conselhos dados sobre o recurso assert no PHP com bugs. Você não quer usar código com bugs. O que você realmente quer são os criadores de PHP para consertar o bug no assert. Até que o façam, você pode usar o assert, mas use-o ciente de seu estado atual de erros.
Além disso, se o recurso assert tiver erros, sugiro que você não o use no código de produção. No entanto, eu recomendo que você o use no desenvolvimento e teste de código quando apropriado.
Finalmente - se você fizer um estudo de design por contrato, descobrirá que há consequências em usar asserções booleanas à luz da herança clássica orientada a objetos - isto é - você nunca deve enfraquecer uma pré-condição, nem enfraquecer uma pós-condição. Fazer isso pode ser perigoso para seus objetos descendentes polimórficos interagindo uns com os outros. Até você entender o que isso significa - eu deixaria isso pra lá!
Além disso, eu recomendo fortemente que os criadores do PHP façam um estudo abrangente de design por contrato e tentem colocá-lo no PHP o mais rápido possível! Então, todos nós podemos nos beneficiar de ter um compilador / interpretador compatível com DbC, que lidaria com os problemas observados nas respostas (acima):
NOTA: Até mesmo o uso de uma
if
instrução -como um substituto para a afirmação (pré-condição) sofrerá consequências terríveis se usado para fortalecer uma pré-condição ou enfraquecer uma pós-condição. Para entender o que isso significa, você precisará estudar design por contrato para saber! :-)Feliz estudando e aprendendo.
fonte