Boas práticas com exceções
ResumoCapturar o que você pode tratar, preservar o stack trace, não usar exceção como fluxo normal e registrar antes de decidir. Boas práticas de exceção reduzem tempo de diagnóstico em produção.
1. Objetivos de Aprendizagem#
- Aplicar o princípio "capture só o que trata".
- Preservar contexto (stack trace e inner exception).
- Distinguir erro esperado de excepcional.
2. Pré-requisitos#
- Exceções customizadas (tópico 10.2).
3. Conceito#
Princípios centrais:
- Capture o que você trata: se não sabe o que fazer com a exceção, deixe-a subir para quem sabe (ex.: o middleware de erros).
- Preserve o rastro: relance com
throw;, nãothrow ex;. - Não use para fluxo normal: entradas previsíveis usam
TryParse/validação, não exceções. - Registre antes de engolir: todo
catchque decide continuar deve, no mínimo, logar. - Falhe cedo: valide argumentos no início (
ArgumentNullException.ThrowIfNull).
O porquê: exceções são caras e, mal usadas, escondem bugs. Bem usadas, tornam falhas visíveis e diagnosticáveis.
4. Mão na Massa#
4.1. Setup#
dotnet new console -n Catalog.ExBoas
cd Catalog.ExBoas
4.2. Implementação Passo a Passo#
- Validação de argumentos (falhe cedo):
void Processar(string nome)
{
ArgumentException.ThrowIfNullOrWhiteSpace(nome);
// ... segue com nome garantidamente válido ...
}
- Relançar preservando o stack trace:
try
{
// operação
}
catch (Exception ex)
{
// Log.Error(ex, "Falha ao processar");
throw; // preserva a origem — NÃO use "throw ex;"
}
- Erro esperado sem exceção:
if (!int.TryParse(entrada, out var n))
{
// trata como fluxo normal, sem exceção
Console.WriteLine("valor inválido");
}
4.3. Executando#
dotnet run
5. Exemplo Completo#
Validar argumentos com ThrowIfNullOrWhiteSpace, relançar com throw; e usar TryParse para entradas previsíveis é a combinação que mantém o código robusto sem abusar de exceções.
6. Boas Práticas e Armadilhas#
| Faça | Evite |
|---|---|
| Deixar subir o que você não trata | Capturar tudo "por segurança" e engolir |
throw; para preservar o rastro | throw ex; (reinicia o stack trace) |
| Logar no ponto de decisão | catch vazio silencioso |
Guards no início (ThrowIfNull) | Deixar null viajar e estourar longe da causa |
Atençãoem uma Web API, o padrão é não ter try/catch espalhado nos controllers: um middleware global centraliza o tratamento e a conversão para respostas HTTP (ProblemDetails).
7. Segurança e Produção#
- Logue exceções com contexto suficiente para diagnóstico, mas sem dados sensíveis (senhas, tokens, PII).
- Nunca devolva o stack trace ao cliente em produção — só uma mensagem genérica e um identificador de correlação.
8. Exercícios#
- Fácil: substitua um
catch (Exception)que engole por um que loga e relança comthrow;. - Médio: adicione guards com
ArgumentException.ThrowIfNullOrWhiteSpacea um método. - Desafio: refatore um trecho que usa exceção como fluxo normal para usar
TryParse.
9. Resumo#
Capture só o que trata, preserve o rastro (throw;), não use exceção como fluxo normal, logue antes de engolir e valide cedo. Na API, centralize o tratamento num middleware.
10. Próximos Passos#
Encerramos exceções. A seguir, o pilar da web moderna: programação assíncrona.
11. Referências#
- Microsoft Learn — Melhores práticas com exceções
- Microsoft Learn — Validação de argumentos (ThrowIfNull)
- Microsoft Learn — Tratamento de erros no ASP.NET Core