我不相信本地捕获是一种反模式,实际上,如果我没记错的话,它实际上是在Java中强制执行的!
对于我来说,实施错误处理的关键是整体策略。您可能需要一个过滤器来捕获服务边界处的所有异常,您可能想要手动拦截它们-只要有一个整体策略,这两个都很好,这将属于您团队的编码标准。
就个人而言,我可以在执行以下操作之一时捕获函数内部的错误:
- 添加上下文信息(例如对象的状态或正在发生的事情)
- 安全地处理异常(例如TryX方法)
- 您的系统越过服务边界并调用外部库或API
- 您想捕获并抛出其他类型的异常(也许将原始异常作为内部异常)
- 该异常是作为某些低价值后台功能的一部分引发的
如果不是这些情况之一,则不添加本地try / catch。如果是这样,则根据情况,我可以处理异常(例如,返回错误的TryX方法)或重新抛出异常,以便全局策略可以处理该异常。
例如:
public bool TryConnectToDatabase()
{
try
{
this.ConnectToDatabase(_databaseType); // this method will throw if it fails to connect
return true;
}
catch(Exception ex)
{
this.Logger.Error(ex, "There was an error connecting to the database, the databaseType was {0}", _databaseType);
return false;
}
}
或重新抛出示例:
public IDbConnection ConnectToDatabase()
{
try
{
// connect to the database and return the connection, will throw if the connection cannot be made
}
catch(Exception ex)
{
this.Logger.Error(ex, "There was an error connecting to the database, the databaseType was {0}", _databaseType);
throw;
}
}
然后,您可以在堆栈顶部捕获该错误,并向用户显示一个友好的用户友好消息。
无论采用哪种方法,在这种情况下都值得创建单元测试,因此您可以确保功能不会更改,并且以后不会干扰项目的流程。
您没有提到您使用的是哪种语言,而是成为.NET开发人员,而且已经看到很多次了,更不用说了。
不要写:
catch(Exception ex)
{
throw ex;
}
采用:
catch(Exception ex)
{
throw;
}
前者重置堆栈跟踪,使您的顶级捕获完全无用!
TLDR
本地捕获不是一种反模式,它通常可以是设计的一部分,并且可以帮助向错误添加其他上下文。