如何在没有大量样板代码的情况下为异常添加上下文?

时间:2009-03-23 14:02:54

标签: .net exception-handling

在我目前的项目中,我看到很多这类代码:

public User GetUserByName(string userName) 
{
    try
    {
        // Lots of code here to check if the user is in the cache,
        // get it from the DB if not, set properties on it, etc...
    }
    catch (Exception ex)
    {
        throw new Exception("Exception getting user by name, username: " + userName, ex);
    }
}

我很欣赏这里的意图,让局部变量对于调试非常有用,但是在每个方法周围放置一个try / catch似乎是太多的工作,它实际上没有帮助可读性。现在我忽略了这样一个事实,即我们抛出一个System.Exception,自然一个更具体的类型会更好,但它不是我的问题的焦点。此外,它可能会被大量复制和粘贴,而不会对异常消息进行任何修改......

所以我的问题是:如何捕获这种上下文信息(例如上例中的用户名)进行调试?让我们假设为了问题的目的,该方法编写良好,并且任何特定的异常检查都得到了处理,我想要的是为任何无法处理的异常添加上下文在这里,需要冒泡到顶级处理程序。

我的第一个想法:

  1. 依靠日志记录框架来跟踪每个方法调用及其参数,这些参数实际上也是样板文件,并且远远超过了适合生产的日志记录。

  2. 引入一些AOP并拦截每个方法(或有限的子集),检查返回的异常并记录参数或将它们添加到抛出的异常中。

  3. 欢迎任何其他意见!

3 个答案:

答案 0 :(得分:1)

我添加带有方法名称的日志消息,然后重新抛出异常。只有在不可预见的条件下才会出现异常,因此需要程序员使用才能修复。程序员最重要的事情是知道异常发生的位置以及日志消息的作用(如果它是通用方法名称,我也将类名添加到日志消息中)。

public User GetUserByName(string userName) 
{    
    try    
    {        

    }    
    catch (Exception ex)   
    {        
       logger.Error("Exception GetUserByName. " + ex.Message);
       throw;
    }
}

答案 1 :(得分:0)

你的Try-Catch块应该只围绕能够抛出异常的代码片段(任何涉及用户输入的内容,任何涉及外部数据源的内容) 在这些情况下,最好只记录相关的局部变量。这些异常是预期的(不可避免),因此您需要以区分预期错误和代码错误的方式记录它们。

如果您没有在邮件中添加额外的上下文,那么您就是在滥用日志工具。捕获和重新捕获总是更好,而不是完全不捕获(它执行finally块),但是你还应该为每个日志消息添加一个相关的注释,否则你实际上会破坏你调试代码的能力,因为你有不知道抛出异常的地方。

此外,.Log文件很便宜,每当你抛出错误时,在它们中都有很多信息是没有害处的。您拥有的错误记录越多,调试生产应用程序就越容易。

答案 2 :(得分:0)

Thrown Exception是代码的正常行为。没有理由挖掘日志以找出原因或者是谁。并更改您的代码,使其永远不会再发生。

抛出异常意味着出错。但不是代码。这可能是数据库连接,用户输入,其他环境问题。

唯一可以捕获日志的异常是Logic的原因。找出程序员出错的地方。只有这个例外你必须修复和记录。所有其他异常应该在适当的抽象级别被捕获而不重新抛出。