É mais sensato registrar exceções em uma classe de exceção pega-tudo ou em uma base?

15

Estou no processo de refatoração de um aplicativo da web bastante grande. Um dos principais problemas é o tratamento inconsistente de erros e estou tentando criar uma estratégia sensata. Eu criei um manipulador de erro personalizado, via set_error_handler que essencialmente transforma erros PHP em ErrorExceptions e uma classe de exceção de base personalizada, que herda diretamente de Exception .

Na produção, estou usando uma exceção genérica catch-all, via set_exception_handler , e estou prestes a adicionar logging de exceção * ao mix. Meu dilema é onde fazer o registro atual, na classe de exceção de base ou no catch-all.

Pensei em algumas razões para registrá-lo no resumo:

  • Existem algumas exceções no código que precisam ser convertidas em algum filho apropriado da classe de exceção base. Até que isso aconteça, nem todas as exceções serão registradas.
  • De alguma forma, parece mais natural fazer isso no catch-all, uma classe de exceção básica não deve fazer mais do que ser apenas isso. (Pode ser um princípio de responsabilidade única, mas pode ser apenas um sentimento equivocado)

e um motivo para efetuar login na classe de exceção de base:

  • Atualmente, o pega-tudo é usado apenas na produção. Seria fácil apresentá-lo em nossos outros ambientes (desenvolvimento, teste), mas isso exigiria alguns ajustes, pois os erros são tratados de maneira diferente por ambiente, já que na produção eles são traduzidos para páginas de erro 404/503.

Existe alguma prática aceitável para onde registrar exceções?

* O registro envolverá a gravação em um arquivo de texto em um primeiro momento, e ele pode evoluir para enviar e-mails para certos tipos de exceções.

Alguns esclarecimentos, solicitados pela resposta do @ unholysampler :

Estou diante de uma base de código sloc de 2 * 10 ^ 6, com muitas coisas de terceiros sobre as quais não tenho controle, e alguns códigos têm controle sobre exceções pré-datas no PHP. E também há algum código recente de baixa qualidade, estamos nos recuperando de um longo período de intensa pressão em que praticamente tivemos que parar de pensar e apenas hackear.

Estamos ativamente refatorando para resolver todas as inconsistências e introduzir uma abordagem sensata de tratamento de erros, mas isso levará algum tempo. Estou mais interessado no que fazer até chegar ao ponto em que os erros são tratados adequadamente. Provavelmente vou fazer outra pergunta sobre uma estratégia sensata de exceção em algum momento.

A principal motivação por trás do registro é obter um e-mail no meu telefone sempre que algo ruim acontece na produção. Eu não me importo se os dumps de dados ficarem enormes, se eu fizer isso, eu terei um trabalho cron apagando os antigos de vez em quando.

    
por yannis 24.11.2011 / 05:11
fonte

2 respostas

11

Em suma, a única vez que você deve registrar a existência de uma exceção é quando você está lidando com isso.

Quando você lança uma exceção, é porque seu código atingiu um estado em que não pode continuar corretamente. Ao lançar uma exceção, você está representando uma mensagem específica para o seu programa sobre o erro que ocorreu. Você não deve pegar uma exceção até que esteja em um ponto em que possa ser tratada corretamente.

O código que você escreve como parte do seu aplicativo principal deve estar ciente dos tipos de exceções que podem ser lançadas e quando elas podem ser lançadas. Se você não pode fazer nada produtivo com uma exceção, não o pegue. Não registre uma exceção até que ela esteja sendo manipulada. Apenas o código de manipulação sabe o que a exceção significa no contexto do fluxo do programa e como responder a ele. Escrever uma mensagem de log aqui pode fazer sentido aqui. Se você usar uma estrutura de registro, poderá definir um nível de registro para a mensagem e, potencialmente, filtrá-los. Isso funciona bem para exceções que podem ocorrer, mas não são críticas e podem ser recuperadas de forma limpa.

Sua exceção catch-all, é seu último esforço para impedir que seu código cause uma morte feia. Se você chegou até aqui, registre todas as informações de estado e erro possíveis. Então você faz o seu melhor para informar ao usuário que o programa está falhando antes que tudo pare. Seu objetivo deve ser nunca ter esse código executado.

Incorporar o registro na classe base não segue as diretrizes acima. A classe base não sabe nada sobre o estado do código. (Ter o rastreamento de pilha não conta porque você não vai escrever código que toma decisões com base na análise.) A classe base não pode fazer nada para indicar a gravidade ou como a exceção pode ser manipulada. Você não quer enormes despejos de dados e rastreamentos de pilha toda vez que há uma exceção simples que você pode manipular e recuperar de forma limpa.

    
por 24.11.2011 / 05:50
fonte
3

Se o seu idioma / tempo de execução não permitir que você determine facilmente a origem da exceção, há motivos para registrá-lo no lançamento. C ++ e alguns mecanismos JS não expõem o arquivo + linha ou a pilha de chamadas da exceção no momento em que você a detectou /, mas essas informações estão disponíveis no momento em que você constrói a exceção.

Nossa solução foi fornecer um mecanismo que usou a configuração de tempo de execução para permitir o registro do tipo da exceção junto com uma pilha barata ao tentar diagnosticar esses problemas.

    
por 24.11.2011 / 09:37
fonte