Pergunta

Devo captura exceções para fins de registro?

public foo(..)
{
   try
   {
     ...
   } catch (Exception ex) {
     Logger.Error(ex);
     throw;
   }
}

Se eu tiver isso no lugar em cada uma das minhas camadas (DataAccess, negócios e WebService) significa que a exceção é registrado várias vezes.

Será que faz sentido fazê-lo se as minhas camadas estão em projetos separados e apenas as interfaces públicas têm try / catch neles? Por quê? Por que não? Existe uma abordagem diferente, eu poderia usar?

Foi útil?

Solução

Definitivamente não. Você deve encontrar o local correto para alça a exceção (na verdade, fazer algo, como catch-e-não-rethrow), e, em seguida, registrá-lo. Você pode e deve incluir todo o rastreamento de pilha, é claro, mas seguindo sua sugestão seria lixo o código com blocos try-catch.

Outras dicas

A menos que você estiver indo para mudar a exceção, você deve registra somente no nível onde você está indo para lidar com o erro e não relançar-lo. Caso contrário, seu log só tem um monte de "ruído", 3 ou mais da mesma mensagem registrada, uma vez em cada camada.

Meu melhor prática é:

  1. Apenas try / catch em métodos públicos (em geral; obviamente, se você está prendendo para um erro específico que você gostaria de verificar para ele lá)
  2. Apenas log na camada UI direita antes de suprimir o erro e redirecionar para uma página de erro / formulário.

A regra geral é que você só pegar uma exceção se você pode realmente fazer algo sobre isso. Assim, na camada de negócios ou de dados, você só iria capturar a exceção na situação de como isto:

            try
            {
                this.Persist(trans);
            }
            catch(Exception ex)
            {
                trans.Rollback();
                throw ex;
            }

tentativas camada My Business / dados para economizar os dados -. Se uma exceção é gerada, todas as transações são revertidas ea exceção é enviado para a camada UI

Na camada de interface do usuário, você pode implementar um manipulador de exceção comum:

Application.ThreadException + = novo ThreadExceptionEventHandler (Application_ThreadException);

Qual então lida com todas as exceções. Pode registrar a exceção e, em seguida, exibir uma resposta amigável:

    static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
    {
        LogException(e.Exception);
    }
    static void LogException(Exception ex)
    {
        YYYExceptionHandling.HandleException(ex,
            YYYExceptionHandling.ExceptionPolicyType.YYY_Policy,
            YYYExceptionHandling.ExceptionPriority.Medium,
            "An error has occurred, please contact Administrator");
    } 

No código UI real, você pode pegar indivíduo exceção de se você está indo fazer algo diferente -. Tais como exibição de uma mensagem amigável diferente ou modificar a tela, etc

Além disso, apenas como um lembrete, sempre tentar manipular erros - por exemplo, dividir por 0 -., Em vez de lançar uma exceção

É uma boa prática é traduzir as exceções . Não basta registrá-los. Se você quer saber o motivo específico uma exceção foi lançada, lançar exceções específicas:

public void connect() throws ConnectionException {
   try {
       File conf = new File("blabla");
       ...
   } catch (FileNotFoundException ex) {
       LOGGER.error("log message", ex);
       throw new ConnectionException("The configuration file was not found", ex);
   }
}

Use suas próprias exceções para embrulhar exceção inbuild. Desta forma, você pode distinta entre erros conhecidos e desconhecidos quando pegar exceção. Isso é útil se você tiver um método que chama outros métodos que são provavelmente jogando excpetions reagir em cima esperado e fracassos inesperados

Você pode querer pesquisar estilos de tratamento de exceções padrão, mas o meu entendimento é o seguinte:. Exceções alça no nível onde você pode adicionar detalhes extra para a exceção, ou no nível em que você vai apresentar a exceção para o usuário

no seu exemplo você está fazendo nada, mas captura a exceção, registrando-a e jogando-o novamente .. porque não basta pegá-lo ao mais alto nível com um try / catch em vez de dentro de cada método se tudo que você está fazendo é logging -lo?

i só iria lidar com isso nesse nível, se você estava indo para adicionar algumas informações úteis para a exceção antes de jogá-lo novamente - enrole a exceção em uma nova exceção de criar que tem informações úteis para além do texto exceção baixo nível que geralmente significa pouco a ninguém sem algum contexto ..

Às vezes você precisa de dados que não está disponível onde a exceção é tratada log. Nesse caso, é apropriado para iniciar sessão só para tirar isso da informação.

Por exemplo (pseudocódigo Java):

public void methodWithDynamicallyGeneratedSQL() throws SQLException {
    String sql = ...; // Generate some SQL
    try {
        ... // Try running the query
    }
    catch (SQLException ex) {
        // Don't bother to log the stack trace, that will
        // be printed when the exception is handled for real
        logger.error(ex.toString()+"For SQL: '"+sql+"'");
        throw ex;  // Handle the exception long after the SQL is gone
    }
}

Este é semelhante ao corte retroativo (minha terminologia), onde tampão um log de eventos, mas não escrevê-los a menos que haja um evento de disparo, como uma exceção sendo lançada.

Se você é obrigado a registrar todas as exceções, então é uma idéia fantástica. Dito isto, registrando todas as exceções sem outra razão não é tal uma boa idéia.

Você pode querer fazer logon no mais alto nível, que normalmente é sua interface do usuário ou código de serviço web. Registrando várias vezes é uma espécie de resíduos. Além disso, você quer saber toda a história quando você está olhando para o log.

Em uma de nossas aplicações, todas as nossas páginas são derivados de um objeto BasePage, e esse objeto alças lidar com a exceção e registro de erros.

Se essa é a única coisa que ele faz, eu acho que é melhor para remover o try / catch de partir dessas classes e deixe a exceção ser elevado para a classe que é responsável em lidar com eles. Dessa forma, você obter apenas um log por exceção dando-lhe registros mais claras e até mesmo você pode registrar o stacktrace para que você não vai perder a partir de onde a exceção foi originada.

Meu método é registrar as exceções apenas no manipulador. O manipulador de 'real' por assim dizer. Caso contrário, o log será muito difícil de ler e o código menos estruturado.

Depende da Exceção: se isso realmente não deveria acontecer, eu definitivamente iria registrá-lo. Na outra maneira: se você espera que essa exceção que você deve pensar sobre o design do aplicativo

.

De qualquer maneira:. Você deve pelo menos tentar especificar a exceção de que quer relançar, captura ou log

public foo(..)
{
   try
   {
     ...
   }
   catch (NullReferenceException ex) {
     DoSmth(e);
   }
   catch (ArgumentExcetion ex) {
     DoSmth(e);
   }
   catch (Exception ex) {
     DoSmth(e);
   }
}

Você vai querer fazer logon em um limite de camada. Por exemplo, se a sua camada de negócios pode ser implantado em uma máquina fisicamente separada em um aplicativo de n camadas, então faz sentido para registrar e lançar o erro desta forma.

Desta forma você tem um registro de exceções no servidor e não precisa ir bisbilhotando máquinas clientes para descobrir o que aconteceu.

Eu uso esse padrão em níveis empresariais de aplicativos que usam serviços web Remoting ou ASMX. Com WCF você pode interceptar e registrar uma exceção usando um IErrorHandler anexado ao seu ChannelDispatcher (outro assunto completamente.) - para que você não precisa do / catch / padrão tentativa lance

Você precisa desenvolver uma estratégia para lidar com exceções. Eu não recomendo a captura e relançar. Além do log supérfluo entradas torna o código mais difícil de ler. Considere escrever para o log no construtor para a exceção. Este reservas do try / catch para exceções que deseja recuperar de; tornando o código mais fácil de ler. Para lidar com exceções inesperadas ou irrecuperáveis, você pode querer um try / catch perto da camada mais externa do programa para registrar as informações de diagnóstico.

BTW, se este for C ++ seu bloco catch é a criação de uma cópia do objeto de exceção que pode ser uma fonte potencial de problemas adicionais. Tente pegar uma referência ao tipo de exceção:

  catch (const Exception& ex) { ... }

Este Rádio software Engenharia podcast é uma boa referência para as melhores práticas de manipulação de erro. Há realmente 2 palestras.

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