Usando afirmações versus lançando exceções?

38

Frequentemente, quando escrevo uma função, quero garantir que as entradas sejam válidas para detectar esses erros o mais cedo possível (acredito que sejam chamados de pré-condições). Quando uma pré-condição falha, sempre lancei uma exceção. Mas estou começando a duvidar se essa é a melhor prática e, se não, as afirmações seriam mais apropriadas.

Então, quando devo fazer o que: quando é apropriado usar uma asserção e quando é apropriado lançar uma exceção?

gablin
fonte
3
Acho que essa pergunta deve ser feita no stackoverflow, embora provavelmente já tenha sido feita uma dúzia de vezes lá, portanto você já deve encontrar muitas respostas.
user281377

Respostas:

50

As asserções devem ser usadas apenas para verificar condições que devem ser logicamente impossíveis de serem falsas (leia-se: verificações de sanidade). Essas condições devem se basear apenas nas entradas geradas pelo seu próprio código. Qualquer verificação baseada em entradas externas deve usar exceções.

Uma regra simples que eu sigo a seguir é verificar os argumentos de funções privadas com afirmações e usar exceções para argumentos de funções públicas / protegidas.

Nota para pensar em um nome
fonte
Bom ponto sobre o uso de exceções para entradas externas. Eu também adicionaria saídas a isso também - problemas ao tentar criar / gravar em arquivo / banco de dados etc.
ChrisF
13
E, inevitavelmente, você encontrará essas afirmações sendo acionadas na produção. +1 para verificar itens particulares com afirmações! Talvez você possa dizer "use afirmações quando estiver no controle total das entradas"?
Frank Shearar
11
Em java, pelo menos, você normalmente deve habilitar a verificação de asserção com o parâmetro de linha de comando -ea. Isso significa que as asserções são efetivamente não-ops, a menos que você as ative explicitamente.
Bill Michell
29

As asserções são usadas para encontrar erros de programação. Seus programas devem funcionar tão bem quando todas as asserções são removidas.

Exceções, por outro lado, são para situações que podem acontecer mesmo quando o programa é perfeito; eles são causados ​​por influências externas, como hardware, rede, usuários etc.

user281377
fonte
Esta é uma maneira muito boa de colocar isso. Se o usuário digitar algo incorreto, lance uma exceção. Se a entrada estiver correta, mas algo ainda estiver errado, faça uma afirmação.
Mateen Ulhaq 22/10/1918
3

A prática típica de programação é compilar asserções a partir de compilações de produção / lançamento. As asserções ajudarão apenas durante os testes internos a detectar falhas nas suposições. Você não deve assumir o comportamento de agências externas; portanto, não deve afirmar sobre eventos da rede ou do usuário. Também é uma boa prática escrever código de manipulação para compilações de produção, caso uma asserção falhe.

Por exemplo, em C,

int printf(const char *fmt, ...)
{
  assert(fmt);  // may fail in debug build but not in production build
  if (!fmt) return -1; // handle gracefully in production build
  ...
}

As exceções devem ser incorporadas às construções de produção. A alternativa para exceção é retornar erro e não asserções.

aufather
fonte
2
Não acho uma boa idéia colocar um comportamento gracioso por trás de uma afirmação para a mesma condição. Inevitavelmente, como o comportamento normal existe apenas na versão de produção, o código que deveria lidar com o comportamento normal será mal testado e trava tão mal quanto, se não pior, o código teria se não fosse guardado.
Sebastian Redl
0

Um problema com as afirmações para mim é que elas estão desativadas por padrão em Java.

Usamos uma estratégia de falha em que o programa - que pode estar sendo executado há anos - precisa travar o mais cedo possível para evitar a corrupção de dados em caso de dados incorretos (de forma inesperada). É para isso que usamos a verificação e, usando afirmações, basicamente arriscamos que elas não sejam ativas.


fonte