【问题标题】:Catching all exceptions for detailed logging purposes - pros and cons捕获所有异常以进行详细的日志记录 - 优点和缺点
【发布时间】:2014-08-25 15:36:10
【问题描述】:

我正在编写一个保存和加载系统,将游戏对象保存为 JSON 兼容格式并重新加载它们。保存对象很好,而且相当简单。但是,我正在尝试使加载过程更加安全,并且更容易查明错误。显然,当我从 JSON 文件加载数据时,所有内容都是从字符串转换的,可能会出现各种用户错误。

每个对象加载方法都包含类似的东西---

public void Load() 
{
    try
    {
        // Deserialize..
        // Potential for all kinds of exceptions, invalid casts, missing info, etc..
        // For eg:

        bool active = data.GetField("active").Value<bool>();

        // GetField() throws an exception if the field doesn't exist.
        // Value<T>() throws an exception if it's an invalid cast, etc.
    }
    catch(Exception e)
    {
        // ..and those exceptions get caught and logged here.
        Logger.LogError(e.ToString, this);
    }
}

在对象 Load 方法中捕获所有异常的好处之一是,当使用对象作为参数调用“LogError()”时,它将突出显示 IDE 层次结构中引发错误的违规对象(无论是哪一个)都可以非常快速地找到有错误的对象并调试它的脚本或保存的数据。

这是引发和捕获异常的适当用法,还是我应该实施更好的设计模式?

感谢您的宝贵时间, 山姆

【问题讨论】:

    标签: c# exception logging load try-catch


    【解决方案1】:

    总是有很多关于catching the exceptionsdifferent but close 意见,但是对于您的任务,给定的方法是简单可行的。我建议您做的唯一一件事就是让异常冒泡:

    catch(Exception e)
    {
        // ..and those exceptions get caught and logged here.
        Logger.LogError(e.ToString, this);
        throw;
    }
    

    记录是个好主意,但如果加载失败,你的程序应该怎么做?只需注销并继续?可能是这种情况,但这种加载方法看起来像是程序的重要组成部分。它看起来不像是一些可能失败或工作我不在乎的背景工作。好吧,它是你的程序,我不知道要求或上下文 - 只是我的意见。

    您应该基于您的异常处理的主要原则是:仅在您可以对它们执行某些操作的时间和地点捕获异常(重试,在方法中获取一些相关的当前数据...) , 以其他方式捕获它们 在调用层次结构中尽可能高(在您的主循环或全局异常处理程序中 - 越高越好,这意味着您需要复制的异常处理越少)。如果你不能做任何能保证你的程序状态一致性的异常——不要抓住它。

    理想情况下,所有类都应该能够适应失败 - 如果它们失败,它们要么失败并且之后不做任何事情,要么将它们的状态恢复到正常。最理想的解决方案是,如果他们在异常情况下回滚任何操作的副作用 - 类似事务的行为。但在现实生活中,这是一个难以实现的目标。

    另外,如果您不喜欢类似的 try-catch 构造来记录代码中的任何位置(它们很重要,但它们并没有做任何实际工作 - 它们的存在对于理解主要工作流程不是必需的),你可以试试Aspect Oriented Programming technologies

    【讨论】:

    • 谢谢尤金。通常我会同意发送异常,但在这种情况下,它与我使用的 IDE/引擎有点不同。对 Logger.LogError 的调用实际上在引擎中重现了某种异常。因此,它再次抛出异常是类似的,但是在选择异常消息时,添加了额外的好处,它实际上它将实际上突出显示违规对象。如果我在这种情况下使用“抛出”发送异常,它只会导致额外的异常,而没有自动突出显示的好处。
    • 所以我同意,我已经找到了许多不同的方法来处理错误处理,而且我的案例与大多数示例场景(与我上面提到的)有些不同。我只是想确保我以一种普遍接受的方式来处理它。感谢您提供有关 AOP 的链接,我一定会读一读,有趣的东西 :)
    【解决方案2】:

    您的问题仍然缺少许多基本内容,例如“数据”是什么类型的对象,是字符串、类还是任何其他类型。

    只要您的代码处理所有可能发生的异常,那么捕获异常对性能永远不会有好处。 仍然可能存在引发异常的情况。

    我建议检查字段而不是直接调用具有该名称的字段,例如,

    bool active = data.HasField("active") ? data.GetField("active").Value<bool>() : false;
    

    另外,在 catch 作为常见场景中,最好传递异常对象而不是 e.Tostring()

    类似:

    Logger.LogError(e, this);
    

    总而言之,它确实取决于应用程序的应用程序,或者更确切地说是需求的需求。 在 Web 应用程序中,我通常会创建 HttpModule 来记录异常,这样我就不必在代码中到处写 catch 块了。

    public class ExceptionModule : IHttpModule
        {
            public void Init(HttpApplication context)
            {
                context.Error += new EventHandler(OnError);
            }
    
            private void OnError(object sender, EventArgs e)
            {
                //write logging exception logic.
            }
    }
    

    【讨论】:

    • 你好约书亚。对不起,如果我不够清楚。对象数据可以是任何东西,从简单的整数到已序列化为 JSON 字符串表示的复杂类。我同意首先检查该字段,并在完整版本中实施。目前,我只是在尝试重现我的代码可能失败的所有场景并进行适当的处​​理。
    猜你喜欢
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 2020-08-18
    • 1970-01-01
    • 1970-01-01
    • 2022-11-15
    • 1970-01-01
    • 2017-03-13
    相关资源
    最近更新 更多