Que tipo de exceção solicitar argumentos fora do intervalo?

5

Que tipo de exceção devo jogar?

Eu tenho uma classe de console que descreve o retângulo de células que um usuário pode indexar passando uma coordenada:

width, height = 80, 25
console = Console.new(width, height)

x, y = 2, 5
point_on_screen = Point.new(x, y)
console[point_on_screen] = 'a'

Agora estou me perguntando que tipos de exceção lançar quando um índice ocorre fora dos limites. Ou seja, fora dos domínios (constante!) X: [0, largura] e y: [0, altura]. Eu poderia lançar um RangeError ou um ArgumentError * .

  1. Importa que tipo de exceção lançar, desde que a mensagem de erro seja útil?
  2. Devo usar o mesmo tipo de exceção para a construção do console e a indexação? As duas são realmente semanticamente diferentes?

* retornando uma espécie de objeto fora dos limites é possivelmente uma opção melhor - algo como um padrão de objeto nulo - mas não o que eu estou querendo saber aqui.

ArgumentError

Uma opção é lançar um ArgumentError porque o argumento está obviamente errado, as dimensões nunca podem ser não-negativas. Isso é o que eu tiro no exemplo 1, porque devemos saber de antemão que as dimensões devem ser não-negativas.

Exemplo 1:

console = Console new(-3, 4) # Argument error

RangeError

Outra opção é lançar RangeError porque o argumento está fora do intervalo válido. Eu uso estes para indexação. O argumento está sempre fora do alcance se x < 0, mas se x ≥ 0, depende da largura da consola se x estiver no domínio.

Exemplo 2:

console = Console.new(20, 40)
pt = Point.new(-3, 4)
Console[pt] # RangeError
    
por R. Peereboom 09.07.2014 / 17:06
fonte

2 respostas

5

Does it matter which type of exception to throw as long as the error message is useful?

Em casos como este, muitas vezes adiro para os documentos oficiais para definições e exemplos de uso.

Os documentos para RangeError são um pouco concisos:

RangeError
Raised when a given numerical value is out of range.

[1, 2, 3].drop(1 << 100)
raises the exception:
RangeError: bignum too big to convert into long

E, embora os documentos para ArgumentError impliquem o incentivo para um Exception mais específico, um dos exemplos (em negrito abaixo) certamente parece ser uma correspondência em potencial para seu caso de uso:

ArgumentError
Raised when the arguments are wrong and there isn't a more specific Exception class.

Ex: passing the wrong number of arguments
[1, 2, 3].first(4, 5)
raises the exception:
ArgumentError: wrong number of arguments (2 for 1)

Ex: passing an argument that is not acceptable:
[1, 2, 3].first(-4)
raises the exception:
ArgumentError: negative array size

Em geral, as exceções Argument -type são uma forma clara e esperada de transmitir ao chamador que eles forneceram alguns parâmetros inválidos.

Quanto à sua menção a " ... contanto que a mensagem seja útil ... ", digo sim, absolutamente. Sempre tente incluir uma mensagem significativa quando você gerar um erro.

Com relação à alternativa de objeto nulo: Pessoalmente, sugiro que você aumente explicitamente o erro em vez de retornar um objeto nulo (ou algum outro indicador fora dos limites). Código construído com este padrão é atormentado por verificações de nulos constantes e, inevitavelmente, um objeto nulo vai escapar de suas redes de segurança e causar estragos inesperados em seu programa.

Quando estou trabalhando com um software que rotineiramente retorna valores nulos ou valores especiais como um indicador de "algo deu errado", preciso gastar mais ciclos mentais para ter certeza de que estou verificando todas as respostas e que estou procurando os sinalizadores de erro certos. (Mas a convenção é certamente um fator, portanto, se você estiver trabalhando com uma base de código existente que usa o padrão de objeto nulo, talvez seja melhor continuar.)

Veja algumas boas leituras adicionais sobre exceções versus variáveis de erro: As variáveis de erro são um padrão ou um bom design?

    
por 09.07.2014 / 19:26
fonte
0

Você sempre pode criar uma exceção personalizada se não encontrar as exceções que você tem à sua disposição.

class MyUsefulException < Exception
end

raise MyUsefulException, 'Huzzah, my exception lives!!!'
    
por 11.07.2014 / 22:31
fonte