Essa é uma pergunta geral de design, mas estou focada em C # e .NET porque essas são as linguagens com as quais estou trabalhando agora.
Devo criar minhas próprias novas classes de exceção ou cooptar exceções de estrutura existentes para propósitos ligeiramente diferentes?
Por exemplo, estou precisando de uma exceção que indique que um membro (isto é, de um tipo por exemplo) era esperado, mas não foi encontrado durante a leitura de uma montagem usando Mono.Cecil
. A biblioteca de classes base define a exceção MissingMemberException
, que parece comunicar exatamente o que eu quero, mas a descrição diz:
A exceção é lançada quando há uma tentativa de acessar dinamicamente um membro da classe que não existe.
O que não se encaixa exatamente, porque não estou acessando dinamicamente o membro, mas trabalhando com a montagem passivamente.
fonte
Respostas:
Em geral
Subclassificar exceções é uma boa idéia para agrupar as exceções nas famílias ou agrupamentos aos quais eles pertencem. Também permite ao código do cliente a oportunidade de lidar com exceções com base em erros específicos ou de maneira mais geral. Normalmente, divido a árvore em algum lugar próximo à raiz entre os erros lógicos e de tempo de execução (por exemplo, em C ++ the
std::runtime_error
vs.std::logic_error
).Ser capaz de diferenciar entre as exceções do sistema e as exceções do seu aplicativo também é uma boa idéia. Seria estranho se o código do cliente estivesse observando uma falha do sistema de algum tipo, mas capturasse o erro lógico do código (por meio de uma classe base).
Dado este caso e C #
O C # tem uma hierarquia rica e grande de exceções - eu não tentaria escolher uma classe base muito profunda nela. Seguindo o seu exemplo, parece que você está gerando um erro lógico (ou pelo menos um erro de aplicativo); portanto, a classe base ou mesmo essa exceção sugeriria um erro no sistema. A exceção exata pode ser debatida, mas acho que neste caso não é uma boa escolha.
Hierarquia
Eu criaria uma hierarquia que permita distinguir entre erros de sistema e de aplicativo e, posteriormente, entre erros de tempo de execução e erros lógicos. Não tenha medo de usar exceções internas - pegue o erro do sistema e envolva-o em algo mais significativo, considerando o contexto em que está sendo lançado. Não exagere, concentre-se no que seriam as principais exceções. As exceções podem ter descrições textuais exclusivas associadas a elas - use-as para fornecer ao usuário ainda mais detalhes ou dicas sobre o que fazer para corrigir o problema.
fonte
A resposta é obviamente "depende", mas, considerando o seu caso de uso, eu diria que não. Aqui está o porquê:
O C # é uma linguagem orientada a objetos maravilhosa. É tão bom, de fato, que às vezes me pego tentando implementar uma visão fanaticamente purista do que começou como um projeto simples. Isso não me acontece muito quando se escreve JavaScript ou Objective-C ou PHP.
Quando entro nesse "modo", esse tipo de paralisia, um dos sintomas pode ser uma obsessão pelo tratamento de exceções, pelos genéricos e pela metaprogramação. Às vezes, os três juntos. É muito mais provável que seja um problema quando estou trabalhando em algo novo, relativamente desconhecido ou com especificações e objetivos de má qualidade. Em vez de me atrapalhar nos detalhes da implementação , acho, por que tentar criar algo que possa acomodar a maioria dos cenários que eu razoavelmente antecipo? Então, quando eu contornar os detalhes, os alicerces serão estabelecidos e eu escreverei vários métodos pequenos e atarracados, e assim por diante. Talvez alguém trabalhe no código da interface do usuário, eu apenas prestarei esses bons serviços e esses contratos ...
Infelizmente, isso ainda não aconteceu comigo. O que tende a acontecer é que eu começo por esse caminho trabalhando em "infraestrutura" - coisas como:
Castle.Windsor
Interceptors
e agrupam chamadas para membros abstratos com manipulação de exceçãoIRepository
,IUnitOfWork
,IDomainService
,ICrossCuttingValidation
, etc.IFrameworkException
)Quando você se pergunta se a descrição de uma exceção é precisa o suficiente para o seu gosto, você está realmente negando que algum outro recurso crítico seja implementado. A natureza da exceção também é reveladora - não é uma exceção orientada a eventos , ocorre evidentemente longe de qualquer metodologia de entrada (como uma interface do usuário ou um pipe ou algo assim) e é provavelmente determinística por natureza - como em, você não pode prever o que um usuário digitará, mas você pode prever qual montagem você escolherá carregar ou outros enfeites.
A propósito, se a descrição o incomoda tanto, você não pode escrever um método de extensão para substituí-lo no escopo apropriado?
Então, isso é realmente apenas eu projetando minha própria paralisia de abstração e análise em você, mas acho que pode ser apropriado. Eu diria que, para permanecer no lado seguro, apenas subclasse an
Exception
quando:Exception
subclassesfonte
Na minha opinião, as exceções personalizadas fazem sentido apenas em 2 casos:
1) você está desenvolvendo uma API
2) você o usa no seu código para se recuperar de uma falha.
Em qualquer outro cenário, as exceções integradas devem ser suficientes.
No seu caso, você pode usar InvalidArgumentException
fonte