Eu mantenho isso simples.
Uma biblioteca possui um tipo de exceção base estendido de std ::: runtime_error (que é do C ++ aplicável conforme apropriado a outros idiomas). Essa exceção recebe uma sequência de mensagens para que possamos registrar; todo ponto de lançamento tem uma mensagem única (geralmente com um ID exclusivo).
É sobre isso.
Nota 1 : Nas situações em que alguém que está capturando a exceção pode corrigi-las e reiniciar a ação. Adicionarei exceções derivadas para coisas que podem ser potencialmente corrigidas exclusivamente em um local remoto. Mas isso é muito, muito raro (lembre-se que é improvável que o apanhador esteja próximo do ponto de lançamento, assim, corrigir o problema será difícil (mas tudo depende da situação)).
Nota 2 : Às vezes, a biblioteca é tão simples que não vale a pena dar sua própria exceção e o std :: runtime_error fará. É importante apenas ter uma exceção se a capacidade de diferenciá-lo de std :: runtime_error puder fornecer ao usuário informações suficientes para fazer algo com ele.
Nota 3 : Dentro de uma classe, geralmente prefiro códigos de erro (mas eles nunca escapam pela API pública da minha classe).
Observando suas vantagens e desvantagens:
As compensações que vejo incluem:
Mais classes de exceção podem permitir níveis muito detalhados de tratamento de erros para usuários da API (propensos a configuração do usuário ou erros de dados ou arquivos não encontrados)
Mais exceções realmente oferecem controle de grão mais fino? A questão é: o código de captura pode realmente corrigir o erro com base na exceção? Estou certo de que existem situações como essa e, nesses casos, você deve ter outra exceção. Mas todas as exceções listadas acima, a única correção útil, são gerar um grande aviso e interromper o aplicativo.
Mais classes de exceção permitem que informações específicas sobre erros sejam incorporadas à exceção, em vez de apenas uma mensagem de string ou código de erro
Esse é um ótimo motivo para usar exceções. Mas as informações devem ser úteis para a pessoa que as está armazenando em cache. Eles podem usar as informações para executar alguma ação corretiva? Se o objeto for interno à sua biblioteca e não puder ser usado para influenciar nenhuma API, as informações serão inúteis. Você precisa ser muito específico, pois as informações lançadas têm um valor útil para a pessoa que pode obtê-las. A pessoa que a captura geralmente está fora da API pública, portanto adapte suas informações para que possam ser usadas com itens da API pública.
Se tudo o que eles podem fazer é registrar a exceção, é melhor lançar apenas uma mensagem de erro em vez de muitos dados. Como o coletor geralmente cria uma mensagem de erro com os dados. Se você criar a mensagem de erro, ela será consistente em todos os coletores; se você permitir que o coletor crie a mensagem de erro, poderá obter o mesmo erro relatado de maneira diferente, dependendo de quem está ligando e capturando.
Menos exceções, mas incorporando um código de erro que pode ser usado como uma pesquisa
Você deve determinar o clima, o código de erro pode ser usado de maneira significativa. Se puder, você deve ter sua própria exceção. Caso contrário, seus usuários agora precisam implementar instruções de troca dentro de catch (o que anula todo o ponto de ter catch manipular automaticamente as coisas).
Se não puder, por que não usar uma mensagem de erro na exceção (não é necessário dividir o código e a mensagem torna difícil procurar).
Retornando códigos de erro e sinalizadores diretamente de funções (às vezes não é possível a partir de threads)
O retorno de códigos de erro é ótimo internamente. Ele permite que você corrija erros de vez em quando e tenha certeza de corrigir todos os códigos de erro e prestar contas deles. Mas vazá-los pela API pública é uma má ideia. O problema é que os programadores geralmente esquecem de verificar os estados de erro (pelo menos, com uma exceção, um erro não verificado forçará o aplicativo a sair de um erro não tratado geralmente corromperá todos os seus dados).
Implementou um sistema de evento ou retorno de chamada em caso de erro (evita o desenrolamento da pilha)
Esse método é frequentemente usado em conjunto com outro mecanismo de tratamento de erros (não como alternativa). Pense no seu programa do Windows. Um usuário inicia uma ação selecionando um item de menu. Isso gera uma ação na fila de eventos. A fila de eventos eventualmente atribui um encadeamento para manipular a ação. O encadeamento deve lidar com a ação e, eventualmente, retornar ao conjunto de encadeamentos e aguardar outra tarefa. Aqui, uma exceção deve ser capturada na base pelo thread encarregado do trabalho. O resultado da captura da exceção geralmente resulta na geração de um evento para o loop principal, o que acabará resultando na exibição de uma mensagem de erro para o usuário.
Mas, a menos que você possa continuar diante da exceção, a pilha se descontrairá (pelo menos para o encadeamento).