Quando devo subclassificar uma exceção no Python?

10

No meu código, existem cerca de sete lugares onde eu levanto uma exceção. Todas essas exceções são tratadas da mesma forma: imprima um erro no arquivo de log, retorne o estado do software ao padrão e saia.

Durante a revisão do código, meu engenheiro sênior, a quem eu valorizo ​​muito, disse que deveria subclassificar todas essas exceções. Seu argumento é que, no futuro, podemos querer lidar com as exceções de maneira diferente e isso será mais fácil.

Meu argumento é que, atualmente, ele apenas confunde nosso código e, como não sabemos se alguma vez manipularemos as exceções de maneira diferente, devemos deixar o código conciso e, se e quando chegar a hora, então e somente então devemos subtipos. .

Eu gostaria de ouvir qualquer argumento para cada caso.

Esdras
fonte
2
YAGNI ... Você não precisa dele agora e sempre pode adicioná-lo mais tarde sem muita dificuldade.
Robert Harvey
Você tem algum exemplo? Você está apenas levantando Exception, por exemplo, ou erros internos mais específicos?
precisa saber é o seguinte
apenas levantando uma exceção ("descrição específica")
Esdras
@Ezra, pelo menos, você deve ver se há uma exceção interna mais adequada (consulte docs.python.org/2/library/exceptions.html ).
precisa saber é o seguinte

Respostas:

8

Você está certo

O argumento para o seu lado já é mencionado por Robert Harvey: não adicione código que você não precisa no momento, especialmente porque é fácil adicioná-lo mais tarde.

Seu revisor também está certo

Por outro lado, o ponto de vista do revisor também é compreensível:

  • Retornar um genérico Exception()não ajuda muito o chamador: embora a descrição da exceção indique ao ser humano o que está acontecendo, o tratamento de exceções de maneira diferente por meio de programação pode ser impossível. O desenvolvedor que usa seu código pode estar relutante em alterar os tipos de exceções , inclusive por medo (justificado ou não) de quebrar alguma coisa.

    Observe que adicionar exceções personalizadas no momento não é tão difícil :

    class MyCustomException(Exception):
        pass
    

    é tudo o que você precisa. São apenas duas linhas de código (já que você pode nem precisar criar um arquivo separado se colocar exceções personalizadas em um arquivo).

  • O código em si parece melhor, mais legível.

    if price < self.PriceMinValue:
        raise OutOfRangeException("The price is inferior to zero.")
    

    parece um pouco mais legível em comparação com:

    if price < self.PriceMinValue:
        raise Exception("The price is inferior to zero.")
    

    devido à indicação do tipo de exceção:

    • No segundo trecho de código, preciso ler a descrição e adivinhar que o preço está fora da faixa (ou talvez não esteja? Talvez haja casos em que o preço possa ser negativo, como descontos?)

    • No primeiro trecho de código, um vislumbre do tipo fornece uma indicação imediata sobre o erro. Parece que há um conjunto de valores permitidos para um preço e o valor atual está fora desse conjunto.

Então?

Então:

  • Ambas as abordagens são válidas. Se você não subclassificar as exceções quando não precisar de tipos personalizados, estará certo. Quando você faz uma subclasse das exceções porque não custa nada fazer isso e pode ser útil mais tarde, você está certo.

  • Seja consistente com sua equipe. Se sua equipe usa exceções personalizadas extensivamente, use-as.

Arseni Mourzenko
fonte
2
Mas há um meio termo: raise ValueError('The price is less than zero'). Isso é mais específico que a base Exception, mas sem nenhum barulho.
precisa saber é o seguinte
+1 para a afirmação simples "seja consistente", com uma equipe, se você tiver uma, consigo mesmo, se não tiver.
Styne666