Eu escrevi uma função que solicita a entrada de um usuário até que ele insira um número inteiro positivo (um número natural). Alguém disse que eu não deveria lançar e capturar exceções em minha função e deixar que o chamador de minha função lide com elas.
Eu me pergunto o que outros desenvolvedores pensam sobre isso. Também provavelmente estou usando mal exceções na função. Aqui está o código em Java:
private static int sideInput()
{
int side = 0;
String input;
Scanner scanner = new Scanner(System.in);
do {
System.out.print("Side length: ");
input = scanner.nextLine();
try {
side = Integer.parseInt(input);
if (side <= 0) {
// probably a misuse of exceptions
throw new NumberFormatException();
}
}
catch (NumberFormatException numFormExc) {
System.out.println("Invalid input. Enter a natural number.");
}
} while (side <= 0);
return side;
}
Estou interessado em duas coisas:
- Devo deixar o chamador se preocupar com exceções? O ponto da função é que incomoda o usuário até que ele insira um número natural. O ponto da função é ruim? Não estou falando de interface do usuário (o usuário não consegue sair do loop sem a entrada adequada), mas de entrada em loop com exceções tratadas.
- Você diria que a instrução throw (neste caso) é um uso indevido de exceções? Eu poderia criar facilmente um sinalizador para verificar a validade do número e enviar a mensagem de aviso com base nesse sinalizador. Mas isso adicionaria mais linhas ao código e acho que é perfeitamente legível.
O problema é que muitas vezes escrevo uma função de entrada separada. Se o usuário precisar inserir um número várias vezes, eu crio uma função separada para entrada que lida com todas as exceções e limitações de formatação.
exceptions
usr
fonte
fonte
Respostas:
O ponto de uma exceção é que ele permite que um método informe ao chamador que entrou em um estado em que não poderia continuar normalmente, sem forçar a incorporação de um código de erro no valor de retorno.
No seu caso, seu método sabe exatamente o que fazer quando a entrada não for maior que 0. O único motivo para salvar linhas aqui é porque você está lançando a mesma exceção que receberia se a entrada não fosse um número. No entanto, a exceção que você está lançando não representa adequadamente por que seu código não gosta da entrada. Se alguém aparecesse para ver esse código, teria que gastar um tempo extra tentando ver exatamente como as coisas estão funcionando.
fonte
Este é um mau uso de exceções. Para começar, um número não positivo não é uma exceção de formato.
Por que usar exceções? Se você souber que entrada não é permitida, apenas não saia do loop até obter entrada válida do usuário, algo como o seguinte:
fonte
Integer.parseInt()
lança aNumberFormatException
se não puder analisar o argumento de string fornecido. Não há necessidade de você (e você não será capaz) de lançar a exceção você mesmo.Integer.parseInt()
método lançará a exceção para você, se ocorrer, você não poderá lançá-lo você mesmo depois, pois ele já foi lançado.Capture exceções apenas se você pretende fazer algo relevante para a chamada de método atual; ou seja, limpeza, lógica de falha etc. Nesse caso, a captura está apenas enviando uma mensagem ao console, não é relevante para o método sideInput, portanto, pode ser manuseada ainda mais na cadeia / pilha de chamadas.
Pode-se se livrar da tentativa / captura aqui e simplesmente documentar a chamada do método:
Ainda é preciso lidar com essa exceção na cadeia / pilha de chamadas!
fonte
Você não deve lançar e capturar a mesma exceção em um método, acho que o bloco catch capturará a mesma exceção que você está lançando, portanto você não está realmente lançando.
Se
parseInt
foi bem sucedido, então não é umNumberFormatException
.se o lado for menor que zero, você deve lançar a
NegativeSideLengthException
;Crie uma exceção de negócios / personalizada chamada
NegativeSideLengthException
Em seguida,
sideInput
lança NegativeSideLengthExceptionVocê pode até (se quiser) adicionar outro bloco catch para pegar
NegativeSideLengthException
e não ter o método para lançá-lo.Sinalizadores não são uma boa maneira de lidar com exceções.
fonte
Exceções são coisas bastante pesadelos, elas trazem mais complexidades do que resolvem.
Em primeiro lugar, se você não capturar suas exceções, o chamador só poderá fazer
on error resume next
, ou seja, depois de uma semana, você não saberá o que sua função pode lançar e o que fazer com ela:Basicamente, se você os obtiver, precisará ter um entendimento muito bom sobre contratos e garantias de exceção. Isso raramente acontece no mundo real. E também será difícil ler seu código.
Além disso, o mais engraçado é que, se você realmente tem alguma chance de lidar com exceções, precisa da linguagem RAII real, o que é bem humorado, já que Java e .NET são sobre exceções ...
Repetindo isso mais uma vez, mas ...:
http://blogs.msdn.com/b/oldnewthing/archive/2004/04/22/118161.aspx
http://blogs.msdn.com/b/oldnewthing/archive/2005/01/14/352949.aspx
http://www.joelonsoftware.com/items/2003/10/13.html
fonte
: throw(thisexception, thatexception)
essas são absolutamente erradas e nunca devem ser usadas, pois, caso contrário, você será inesperado, exceto.catch
. Embora um valor de retorno ignorado não seja pesquisável - ele é identificável apenas através da revisão de código linha por linha. Por último, mas não menos importante, os construtores não têm valores de retorno, esse é o principal motivo para usar exceções.