Pergunta

Quando você deve lançar uma exceção personalizada?

por exemplo. Eu tenho algum código que se conecta a um servidor. O código que se conecta ao servidor lança um IOException quando não consegue se conectar. No contexto do método é chamado, isso é bom. É também bem no código de rede.

Mas, como isso representa não ter uma conexão (e, portanto, não trabalho) a exceção vai todo o caminho até o ui. Nesta fase, um IOException é muito ambígua. Algo como NoConnectionException seria melhor.

Então, minha pergunta é: Em que fase você deve capturar uma exceção ao invés jogar outro (personalizado) exceção que melhor se encaixa a abstração?

Foi útil?

Solução

Eu esperaria exceções para falar em termos do que eu pedi o método originário de fazer. por exemplo.

read -> ReadException
connect -> ConnectException
buildPortfolio -> FailedToBuildPortfolioException

etc. Este abstrai o que está acontecendo debaixo das cobertas (ou seja, você está conectando através de soquetes etc.). Como regra geral, quando eu criar uma interface para um componente, muitas vezes eu criar uma exceção correspondente ou conjunto de exceções. Minha interface será chamado Component, e meus exceções são geralmente ComponentException (por exemplo RateSource e RateSourceException). É consistente e fácil de exportação para diferentes projetos como um conjunto de componentes completa.

A desvantagem é que você cria um monte de exceções, e você pode ter que executar um monte de traduções. A vantagem é que (como você já identificou), obtém pouco ou nenhum vazamento abstração.

Em algum ponto durante a hierarquia de chamadas de método (e, portanto, exceções) você pode decidir que nenhuma recuperação pode ocorrer (ou é em um lugar inapropriado) e traduzir para exceções não verificadas sejam manuseadas mais tarde.

Outras dicas

Eu sei que este é marcado como "linguagem-agnóstico", mas eu não acho que ele realmente é. Vindo de uma perspectiva C ++, eu espero muito poucas operações básicas para lançar uma exceção - a biblioteca padrão C ++ utiliza apenas exceções em poucos lugares. Então meu próprio código é muitas vezes o primeiro lugar onde as exceções podem ser geradas. Nesse código, eu como uma hierarquia muito plana - Eu não quero ser mexer com centenas de capturas () cláusulas mais tarde no código, e nunca entendi a obsessão aparente Java e C # 's com a criação de heirarchies barrocas de classe e namespace <. / p>

Assim, para o meu código C ++ - um tipo de exceção, que contém uma mensagem de erro significativa, por biblioteca. E um para o executável final.

Eu acho que existem duas questões escondidas aqui: a) Quando se deve esconder uma exceção atrás de uma exceção diferente. b) Quando se deve usar uma exceção personalizada para isso.

a) diria: sempre que uma exceção viaja através da fronteira de duas camadas na aplicação, deve-se escondido atrás de uma exceção que é mais apropriado para a nova camada. Exemplo:., Porque você está fazendo algumas coisas remoto, você recebe um ConnectionWhatEverException

Mas o chamador não deve estar ciente dos problemas de conexão. Desde que ele só quer obter algum serviço realizado, então ele recebe um ServiceOutOfOrderException. A razão para isto é: Dentro da camada, fazendo comunicação remota, você pode fazer algo útil com um ConnectionException (repetição, escrita em um backout fila ..). Uma vez que você deixou essa camada, ninguém sabe como lidar com uma ConnectionException. Mas eles devem ser capazes de decidir, o que fazer, quando o serviço não funciona.

b) Quando não há correspondência de exceção existente. Há um par de Exceção útil em Java, por exemplo. Eu uso IllegalState e IllegalArgument com bastante frequência. Um forte argumento para uma nova classe de exceção é, se você tem algum contexto útil para fornecer. Por exemplo, o nome do serviço que falhou poderia ser um argumento de um ServiceFailedException. Só não criar uma classe para cada chamada de método, ou qualquer coisa nesse sentido. 100 classes de excepção, não é um problema, desde que eles tenham um comportamento diferente (isto é, pelo menos campos diferentes). Se eles diferem apenas pelo nome e residir no mesmo nível de abstração, fazer-lhes uma exceção, e colocar os nomes diferentes na mensagem ou um único campo de que classe de exceção.

c) Pelo menos em java, há a discussão sobre exceções verificadas. Eu envolvo aqueles diretamente em um único desmarcada, porque eu odeio o verificado tipo. Mas isso é mais uma opinião então o conselho.

Existe algum caso em que você iria ficar NoConnectionException que não é causado por um problema IO? Por outro lado, é saber se a causa é baseada IO ou não vai ajudar o cliente a recuperar de forma sensata?

Quando você deve lançar uma exceção personalizada?

I. Quando você pode fornecer mais informações (de diagnóstico).

Nota: Esta informação adicional pode não estar disponível no local onde a exceção original (IOException) foi lançada. camadas progressivas de abstrações podem ter mais informações para adicionar como o que você estava tentando fazer o que levou a essa exceção?

II. Quando você não deve expor os detalhes de implementação: ou seja, você quer que o (ilusão de?) Abstração para continuar.

Isso pode ser importante quando o mecanismo de implementação subjacente pode mudar. Envolvendo a exceção subjacente em uma exceção personalizada é uma boa maneira de isolar seus clientes a partir de detalhes de implementação (levantando o nível de abstração)

III. Ambos I e II

NOTA: Além disso seus clientes deve ser capaz de entrar em sintonia com o nível exato de informações que eles estão interessados ??em ou antes, eles devem ser capazes de sintonizar qualquer coisa que eles não estão interessados ??em Portanto, é uma boa idéia para derivar suas exceções personalizadas a partir. IOException.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top