Pergunta

Estamos revendo um de tratamento de exceção do sistema da empresa e encontrou um par de coisas interessantes.

A maioria dos blocos de código (se não todos eles) estão dentro de um bloco try / catch, e dentro do bloco catch uma nova BaseApplicationException está sendo jogado - o que parece ser proveniente das Bibliotecas Enterprise. Eu estou em um pouco de um problema aqui como eu não ver os benefícios fora de fazer isso. (Jogando um outro excepção a qualquer momento um ocorre) Um dos desenvolvedores quem está usando o sistema por um tempo, disse que é porque essa classe é o encarregado de publicar a exceção (envio de e-mails e coisas assim), mas ele não estava muito certo sobre isso. Depois de passar algum tempo a passar pelo código que eu estou bastante confiante para dizer, isso é tudo que ele faz é recolher informações sobre o meio ambiente e que publicá-lo.

A minha pergunta é: - É razoável para envolver todo o código dentro try {} catch {} blocos e de lançar uma nova exceção? E se for, por quê? Qual é a vantagem?

A minha opinião pessoal é que seria muito mais fácil usar um HttpModule, se inscrever para o evento de erro do evento de aplicação, e fazer o que é necessário dentro do módulo. Se tivéssemos ir por este caminho, será que perdi alguma coisa? Quaisquer inconvenientes?

A sua opinião é muito apreciado.

Foi útil?

Solução

Nunca 1 catch (Exception ex). Período 2 . Não há nenhuma maneira você pode lidar com todos os diferentes tipos de erros que você pode pegar.

Nunca 3 pegar um tipo de derivados de exceção se você não pode lidar com isso ou fornecer informações adicionais (para ser usado por manipuladores de exceção posteriores). Exibindo uma mensagem de erro é não o mesmo que manipulação o erro.

Um par de razões para isso, a partir do topo da minha cabeça:

  • Captura e rethrowing é caro
  • Você vai acabar perdendo o rastreamento de pilha
  • Você vai ter uma baixa relação sinal-ruído em seu código

Se você sabe como lidar com um específica exceção (e redefinir a aplicação de pré-estado de erro), pegá-lo. (É por isso que ele é chamado exceção manipulação .)

Para lidar com exceções que não são apanhados, para ouvir os eventos apropriados. Ao fazer WinForms, você precisa ouvir para System.AppDomain.CurrentDomain.UnhandledException, e - se o seu fazer Threading - System.Windows.Forms.Application.ThreadException. Para aplicações web, existem mecanismos semelhantes (System.Web.HttpApplication.Error)

.

Como para exceções quadro embrulho em seu aplicativo exceções específicas (não) (ou seja throw new MyBaseException(ex);):. Totalmente sem sentido, e um mau cheiro 4


Editar

1 Nunca é uma palavra muito dura, especialmente quando se trata de engenharia, como @ Chris apontou nos comentários. Eu vou admitir a ser alta em princípios quando escrevi pela primeira vez esta resposta.

2,3 Veja 1 .

4 Se você não traz nada de novo para a mesa, eu ainda mantenho a isso. Se você pegou Exception ex como parte de um método que você sabe poderia falhar em qualquer número de maneiras, acredito que o método atual deve refletir que nele de assinatura. E como você sabe, as exceções não é parte da assinatura do método.

Outras dicas

Se eu estou lendo a pergunta corretamente, eu diria que a implementação de um try / catch que exceções interceptar (você não mencionar - é pegar todas as exceções, ou apenas um específico?) E lança uma exceção diferente é geralmente uma coisa ruim.

Desvantagens:

No mínimo você vai perder informações rastreamento de pilha - pilha você vai ver só vai estender-se ao método em que a nova exceção é lançada -. Você potencialmente perder alguma informação boa depuração aqui

Se você está pegando exceção, você está correndo o risco de mascarar exceções críticas, como OutOfMemory ou StackOverflow com uma exceção menos crítica, e, assim, deixando o processo de execução, onde talvez deveria ter sido demolido.

Vantagens possíveis:

Em alguns casos muito específicos você poderia tomar uma exceção que não tem muito valor de depuração (como algumas exceções voltando de um banco de dados) e enrole com uma exceção que acrescenta mais contexto, por exemplo, ID do objeto que estavam lidando com .

No entanto, em quase todos os casos isso é um cheiro ruim e deve ser usado com cautela.

Geralmente você só deve capturar uma exceção quando há algo realista que você pode fazer nessa localização, ou seja, se recuperando, rolando para trás, indo para o plano B etc. Se não há nada que você possa fazer sobre isso, apenas deixe-a passar -se a cadeia. Você só deve capturar e lançar uma nova exceção se houver específica e dados úteis disponíveis nesse local que pode aumentar a exceção original e, portanto, ajuda de depuração.

Eu sou da escola de pensamento onde blocos try / catch deve ser usado e as exceções não relançada. Se você executar o código que é susceptível de erro, então ele deve ser manuseado, registrado e algo retornado. Rethrowing exceção apenas o propósito de re-log mais tarde no ciclo de vida da aplicação.

Aqui está um interessante post sobre como usar um HttpModule para exceções identificador: http://blogs.msdn.com/rahulso/archive/2008/07/13/how-to-use-httpmodules-to -troubleshoot-your-asp-net-Application.aspx e http://blogs.msdn.com/rahulso/archive/2008/07/18 /asp-net-how-to-write-error-messages-into-a-text-file-using-a-simple-httpmodule.aspx

Confira ELMAH . Ele faz o que você está falando. Muito bem.

Quando eu criar bibliotecas tento sempre fornecer um número reduzido de exceções para os chamadores de manusear. Por exemplo, pense em um componente Repositório que se conecta a um banco de dados SQL. Há toneladas de exceções, de exceções cliente de SQL para exceções elenco inválidos, que teoricamente pode ser jogado. Muitos destes estão claramente documentadas e podem ser contabilizados em tempo de compilação. Então, eu pegar o maior número deles que puder, coloque-os em um único tipo de exceção, digamos, um RepositoryException, e deixar que o rolo de exceção na pilha de chamada.

A exceção original é mantido, de modo a exceção original pode ser diagnosticada. Mas meus chamadores só precisa se preocupar sobre como lidar com um único tipo de excepção e não ninhada seu código com toneladas de diferentes blocos catch.

Existem, é claro, alguns problemas com isso. Mais notavelmente, se o chamador pode lidar com algumas dessas exceções, eles têm de raiz em torno da RepositoryException e, em seguida, ligar o tipo de exceção interna para lidar com isso. Sua menos limpas do que ter um bloco de captura individual para um único tipo de excepção. Eu não acho que isso é um grande problema, no entanto.

Parece que a exceção que é lançada não deveria ter sido implementada como uma exceção.

De qualquer forma, eu diria que desde que este BaseApplicationException é uma exceção geral para todos os fins, seria bom para lançar exceções que são específicas ao contexto mais. Então, quando você está tentando recuperar uma entidade a partir de um banco de dados, você pode querer uma EntityNotFoundException. Dessa forma, quando você está depurando você não tem que pesquisar através de exceções internas e rastreamentos de pilha para encontrar a verdadeira questão. Se este BAseApplicationException está a recolher informações sobre a exceção (como manter o controle da exceção interna), então este não deve ser um problema.

Eu usaria o HttpModule só quando eu não poderia ficar mais perto de onde as exceções são realmente acontecendo no código. Você realmente não quero um evento HttModule AoOcorrerErro que é uma instrução switch gigante dependendo informações de erro de BaseApplicationexception.

Para concluir, vale a pena para jogar diferentes exceções quando você pode dar exceções mais específicas que indicam a raiz do direito problema fora do bastão.

Da minha experiência, capturar a exceção, adicione o erro para o Server (?) Objeto. Isso permitirá .NET para fazer o que for preciso fazer, em seguida, exibir a sua exceção.

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