Architecture 你觉得“我的”怎么样;Don';t捕获意外异常“;最佳实践?

Architecture 你觉得“我的”怎么样;Don';t捕获意外异常“;最佳实践?,architecture,exception-handling,Architecture,Exception Handling,我已经读过很多次了,一个人不应该盲目地捕捉异常。 有些人说,可以将Main()封装到catch块中以显示错误,而不只是退出(),但似乎有一种共识,即如果发生意外情况,您永远不应该让程序运行,因为它处于未知状态,并且可能以意外的方式运行 虽然我同意隐藏错误而不是修复错误的观点,但这是一个错误的想法,请考虑下面的情况: 你有一个巨大的服务器。数百万行代码 启动时,它会将所有客户加载到其本地缓存中 对我来说,写这篇文章很有意义: foreach (string CustomerI

我已经读过很多次了,一个人不应该盲目地捕捉异常。 有些人说,可以将Main()封装到catch块中以显示错误,而不只是退出(),但似乎有一种共识,即如果发生意外情况,您永远不应该让程序运行,因为它处于未知状态,并且可能以意外的方式运行

虽然我同意隐藏错误而不是修复错误的观点,但这是一个错误的想法,请考虑下面的情况:

你有一个巨大的服务器。数百万行代码

启动时,它会将所有客户加载到其本地缓存中

对我来说,写这篇文章很有意义:

           foreach (string CustomerID in Customers)
                try
                {
                    LoadCustomer(CustomerID);
                }
                catch (Exception ex) // blind catch of all exceptions
                {
                    // log the exception, and investigate later.

                }
如果没有盲捕获,无法加载单个客户只会使所有服务器崩溃

我当然更喜欢让我的服务器在运行时对一个客户产生一些未知的副作用,而不是让整个服务器停机。

当然,如果我运行catch代码,我要做的第一件事就是修复代码中的bug


这里有我忽略的东西吗?是否有已知的最佳实践(除了“永不捕获意外异常”策略)


是否最好在LoadCustomer()方法中捕获异常,从那里重新调用“CustomerLoadException”,并捕获CustomerLoadException而不是调用代码中的所有异常?

这是一件逐案处理的事情。如果您可以保证加载失败不会对其他客户产生任何影响,那么记录和跳过该特定客户似乎是合理的。不过,并非所有例外都是这样。特别是对于错误情况,例如,通常情况下,问题影响了整个程序的运行,您应该中止。

要解决真正影响程序稳定性的异常,最好编写此类代码:

      foreach (string CustomerID in Customers)
            try
            {
                LoadCustomer(CustomerID);
            }
            catch (Exception ex) // blind catch of all exceptions
            {
                if (ex is OutOfMemoryException || ex is StackOverflowException ||...)
                     throw;
                // log the exception, and investigate later.

            }
我当然更喜欢让我的服务器在运行时对一个客户产生一些未知的副作用,而不是让整个服务器停机。 您如何知道导致LoadCustomer()中出现异常的bug没有引起任何其他问题?总的来说,我想我更喜欢“日志异常,将异常重新抛出到更高的级别”,然后可能退出


在这种情况下,我可能会支持两种处理方法,但一般来说,处理没有明确处理方法的错误并不理想。

我认为您缺少的是桌面应用程序的“最佳实践”不一定与服务器的“最佳实践”相同,这和网页上的不一样

如果一个网页抛出了一个未经处理的异常,您会想到“meh”并点击刷新。如果一个桌面应用程序抛出一个,你可能会丢失一些数据,并且非常恼火。如果服务器抛出一个,在修复之前,您的整个业务可能会停止

这还取决于修补程序的容易程度——如果您可以轻松地将修补程序推送到所有安装(如您自己的服务器或内部应用程序),那么最好不要对异常进行破坏。如果你正在写一些无法修补的东西(一个旧游戏机或嵌入式设备应用程序的游戏),那么你最好接受这个异常


当然,在任何情况下,最好让您的测试捕捉到问题,以便您能够正确地处理它,但我们都知道错误会发生…

我在这方面不是很有经验。然而,在我看来: 1.几乎任何规则都有例外。知道什么时候打破规则很重要。 2.在异常处理的情况下,盲目捕获异常几乎从来都不是一个好主意。这是因为您可能会发现一些真正意想不到的错误

例如,在Python(至少2.5.2)中,盲目捕获将允许我捕获ctrl+c信号(Linux)。这意味着我不能在紧急情况下终止申请

  • 对于Web服务器代码,您可能需要执行以下操作之一
    +使用在客户未能加载和记录/纠正时引发的自定义异常。
    +在更深层次的代码中使用异常处理,并在那个里进行处理

  • 好吧,让我这么说。。比如说神秘的客户无法加载,因为它不存在,比如说因为有人知道如何破解你系统的前端层。现在想象一下,黑客做了各种各样的恶意事情,直到他碰巧触发了一些函数,试图读取客户的未知值,然后才存在。现在,系统无论如何都会崩溃,但黑客能够对无效客户进行各种干扰

    这真的更好吗?

    “这里有我忽略的东西吗?”

    “是否有已知的最佳实践(除了“永不捕获意外异常”策略)

    对。封装。责任分配。原则

    在LoadCustomer()方法中捕获异常、从那里重新调用“CustomerLoadException”以及捕获CustomerLoadException而不是调用代码中的所有异常是否更好


    对。这封装了提供
    loadCustomer
    方法的类定义中可能出错的所有内容。

    我认为这取决于senario,但作为一项规则,我只捕获我期望通过日常使用应用程序发生的异常,并使用某种未经处理的异常报告/日志记录工具,如健康监控ASP.Net。但是,如果应用程序的关键部分不能有未处理的异常,我会捕获所有异常并再次报告/记录它们。

    这是一个健壮性的问题,即使在出现无法解释的错误的情况下,与正确性的问题相比,健壮性仍会继续运行,宁愿彻底失败,也不愿产生不可靠的结果

    很明显,如果你是wor