【问题标题】:Planning an exception handling strategy in advance提前规划异常处理策略
【发布时间】:2017-07-03 21:17:58
【问题描述】:

当我查看 .NET Framework 中的方法时,它可能会抛出几个可能的异常。

从规划的角度来看,要规划和处理这些例外情况,我需要提出什么要求?我知道根据异常的影响,这会影响在 UI 层中显示它。例如,如果对用户体验不透明的后端进程抛出异常,您不希望向用户显示该异常,因为他/她不知道那是什么。

谢谢

【问题讨论】:

  • 托管 VS 编译器将默认异常处理程序放在执行堆栈的顶部,因此代码中任何未处理的异常都会被默认处理程序捕获。因此,在 main 中放置一个异常处理程序将捕获代码中其他处理程序未捕获的所有异常,并将阻止默认处理程序显示不需要的异常消息。

标签: c# .net exception exception-handling


【解决方案1】:

我想把它写成评论,但是评论文本框太长了……

  1. 有些例外情况对用户来说很重要,因为他们可以自己处理,例如:文件名非法。

  2. 我认为向用户展示一些例外情况很重要,因为他们(用户)将充当我的 QA 团队,例如:某些方法不会更新 GUI,他们可能会得出结论,他们应该进一步报告,他们会向我显示异常,我会发现我的数组超出范围......

  3. 有一些例外,将它们推广给用户只会让他们感到困惑,就像你说的那样

“他/她不会知道那是什么”

例如,例如:

“如果后端不透明的进程抛出异常”。

我为自己保存的那些异常(在数据库中..)..
我总是提醒自己,与开发人员相比,最终用户有不同的心理(-:

我希望我以正确的方式理解了您的问题。

【讨论】:

    【解决方案2】:

    您的应用程序中通常会有一个业务逻辑层,并且您会将该库中的方法包装在安全调用中。这些方法甚至可以说明它们可以抛出哪些异常,如果您愿意,您可能希望以独特的方式处理这些异常。

    下面是几个可以处理意外和自定义异常的类的示例:

    class Program
    {
        static void Main(string[] args)
        {
            MethodInvokationResult result = SafeActionInvokator.HandleSafely(() =>
            {
                MyFakeBusinessEngine.DivideTwoNumbers(5, 0);
            });
            if (result.Exception is System.DivideByZeroException)
            {
                Debug.WriteLine($"A divide by zerp exception was caught");
            }
            else if (!result.Success)
            {
                Debug.WriteLine($"An unknown error occured.");
            }
        }
    }
    

    ^ 你可以看到你可以包装调用并以合理的方式处理它们。

    public class MethodInvokationResult
    {
        public bool Success { get; set; }
        public Exception Exception { get; set; }
    }
    

    ^ 一个简单的结果类

    public static class MyFakeBusinessEngine
    {
        /// <summary>
        /// Divides two numbers
        /// </summary>
        /// <param name="a">numerator</param>
        /// <param name="b">denominator</param>
        /// <returns>the result</returns>
        /// <exception cref="System.DivideByZeroException">When b is zero, divide by zero exception is thrown.</exception>
        public static int DivideTwoNumbers(int a, int b)
        {
            return a / b;
        }
    }
    

    ^ 一个有据可查的方法,它甚至可以告诉其他开发人员它期望抛出什么异常

    public static class SafeActionInvokator
    {
        /// <summary>
        /// Executes a method, and if any exception is thrown, will log the error and swallow the exception.
        /// </summary>
        /// <param name="methodToExecute"></param>
        public static MethodInvokationResult HandleSafely(Action methodToExecute)
        {
            try
            {
                methodToExecute.Invoke();
                return new MethodInvokationResult()
                {
                    Exception = null,
                    Success = true
                };
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"{ex}");
                return new MethodInvokationResult()
                {
                    Exception = ex,
                    Success = false
                };
            }
        }
    }
    

    ^ 您调用的方法的包装器,将其包装在 try catch 中,允许您以相同的方式处理所有异常,或将任何您想要的自定义逻辑放入其中。

    这可以扩展为一个可以返回任何实际结果值的调用。你可以创建一个通用的结果类,而不是我展示的那个简单的类。

    终于!至于您的实际问题,我会在您的应用程序中创建其中一些层,并重新抛出任何包含严​​重等级的异常。这些将传播到您的 UI 层,您可以根据严重性选择要执行的操作。

    甚至可能是这样的!

    public class MajorException : Exception { }
    public class MediumException : Exception { }
    public class MinorException : Exception { }
    public class UserError : Exception { }
    

    希望这会有所帮助!

    【讨论】:

    • 这是一个非常方便的技术,谢谢!例如,如果应用程序中有一个关键文件被删除(如配置文件),然后应用程序尝试打开它,那将是一个主要(或致命)异常。在这种情况下,我会关闭应用程序。我想做的是做一个流程图,根据它们的性质描述我在异常情况下应该采取的行动。
    • 流程图是吗?我强烈推荐 yEd Graph Editor - 完全免费而且很棒。我在工作中使用它!只要您可以定义您期望可以处理的异常,就需要一些人的脑力来识别一行代码或代码块可能出现的问题,例如您提到的文件访问。如果你能预料到它,你就能处理它。哎呀,您可以预料到完全崩溃,只要安全处理异常,您的应用程序就可以继续运行。
    • 我应该补充... 您可能需要考虑当某些事情失败时该怎么办,这可能意味着回滚之前的操作。这可能会很麻烦,但是您可以使用 UnitOfWork 模式,也许可以利用 DotNet 框架提供的事务模式......我离题了。
    • 在我的例子中,应用程序是 ASP.NET,它围绕着 AD 帐户的创建和管理展开。大多数操作只有在调用 Save() 方法时才会提交给 AD,因此不可能出现中间状态。我还有一个问题——我在异常处理中只能看到两个选项——记录并告诉用户——当你“处理”一个异常时,还有其他事情要做吗?如果你回滚一个操作,这会进入 catch 还是最终阻塞?
    • 绝对值得你研究工作单元模式和内置事务系统,一个很好的起点:docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions/…
    猜你喜欢
    • 2011-01-23
    • 2016-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-16
    • 1970-01-01
    相关资源
    最近更新 更多